JavaScript温故而知新——原型和原型链
栏目: JavaScript · 发布时间: 6年前
内容简介:在当前Vue、React、Angular三驾马车齐驱的前端领域,我们对于框架的学习是无可厚非的,毕竟日常工作当中做的最多的就是业务的开发,框架的灵活运用大大提高了我们的开发效率。只不过我们前端框架的底层也终归是原生的JS,如果我们对于原生的东西了然于胸,那么对于框架的使用自然是更加得心应手。不过原生JS我们往往用的比较少,这也造成了对于很多概念和原理很容易就被我们所遗忘,这也是我写这个系列的初衷,在自己回顾这些知识的同时将其记录下来,时常拿出来翻看翻看,反复咀嚼,尽量把它牢牢锁在脑海。下面是这个系列的一篇:
在当前Vue、React、Angular三驾马车齐驱的前端领域,我们对于框架的学习是无可厚非的,毕竟日常工作当中做的最多的就是业务的开发,框架的灵活运用大大提高了我们的开发效率。只不过我们前端框架的底层也终归是原生的JS,如果我们对于原生的东西了然于胸,那么对于框架的使用自然是更加得心应手。
不过原生JS我们往往用的比较少,这也造成了对于很多概念和原理很容易就被我们所遗忘,这也是我写这个系列的初衷,在自己回顾这些知识的同时将其记录下来,时常拿出来翻看翻看,反复咀嚼,尽量把它牢牢锁在脑海。
下面是这个系列的一篇:《原型和原型链》
一、原型模式
我们创建的每一个函数都有一个 prototype (原型)属性,这个属性指向的是通过调用构造函数来创建出来的 对象实例 的 原型对象 ,这个原型对象可以让所有对象实例 共享 它所包含的属性和方法。
function Person () {
}
Person.prototype.name = "xiao";
Person.prototype.sayName = function () {
alert('this.name')
}
var person1 = new Person();
var person2 = new Person();
person1.sayName() // "xiao"
console.log(person1.name == person2.name) // "true"
复制代码
上面的例子当中我们创建了一个构造函数 Person ,并通过它的 prototype 属性在它的 原型对象 中定义了 name 属性并赋值,然后通过调用构造函数 Person 实例化出来两个对象实例,通过打印出来的值我们可以得知, person1 和 person2 共享了原型对象中的属性和方法。
构造函数,原型对象和对象实例的关系
我们知道每个函数都有一个 prototype 属性指向函数的原型对象。在默认情况下,所有原型对象都有一个 constructor (构造函数)属性,这个属性指向了 prototype 属性所在的函数,比如前面的例子中, Person.prototype.constructor 就指向 Person 。
另外,当调用构造函数创建一个新实例后,该实例的内部将包含一个 __porto__ 属性(仅在Firefox、Safari、Chrome中支持),这个属性指向的就是构造函数的原型对象。由此我们可以得出以下图示的结论:
通过代码来验证:
# 实例和原型对象之间的关系 console.log(person.__proto__ == Person.prototype) // true # 也可以通过isPrototypeOf()和ES5中的Object.getPrototypeOf()方法来判断 console.log(Person.prototype.isPrototypeOf(person1)) // true console.log(Object.getPrototypeOf(person) === Person.prototype) // true # 原型对象和构造函数的关系 console.log(Person.prototype.constructor == Person) // true 复制代码
二、原型链
通过前面我们对构造函数,对象实例和原型对象三者关系的描述可知,实例都包含了指向原型对象的内部指针。
那么假如现在我们有两个构造函数 A 跟 B ,我们让构造函数 A 的原型对象等于构造函数 B 的实例,根据前面的推论,这个时候 A 的原型对象就包含指向B的原型对象的指针,再假如又有一个构造函数 C ,让 A 的原型对象等于 C 的实例,上述关系依旧成立,以此类推便形成了实例与原型的链条,即原型链,它主要作为JS中实现继承的主要方法。
原型链的基本实现
function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function() {
return this.property;
}
# 继承了SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function() {
return this.subproperty;
}
var instance = new SubType();
console.log(instance.SuperValue()); // true
复制代码
在上面的代码中,我们没有使用 SubType 默认的原型,而是将 SuperType 的实例赋给它,重写了 SubType 的原型对象;这样一来 SubType.prototype 的内部便具有一个指向 SuperType 原型的指针,原来存在于 SuperType 的实例中的所有属性和方法,现在也存在于 SubType.prototype 中了。
instance 同理,还要注意的是由于 SubType 的原型指向了 SuperType 的原型,而 SuperType 的原型的 constructor 属性指向的是 SuperType 构造函数,那么 instance.constructor 也就指向了 SuperType
如下图所示蓝色的线就代表了原型链
原型搜索机制
当访问一个实例属性或方法时,在通过原型链实现继承的情况下,首先会在实例中搜索该属性,在没有找到属性或方法时,便会沿着原型链继续往上搜索,直到原型链末端才会停下来。
这里还有一个重要的点,事实上所有引用类型默认都继承了 Object ,而这个继承也是通过原型链实现的,也就是说,所有函数的默认原型都是 Object 的实例,这也是所有自定义类型都会继承 toString() 、 valueOf() 等默认方法的根本原因。
Object.prototype的原型
既然所有类型默认都继承了 Object ,那么 Object.prototype 又指向哪里呢,答案是 null ,我们可以通过下面的代码打印试试看:
console.log(Object.prototype.__proto__ === null) // true 复制代码
null 即没有值,也就是说属性或方法的查找到 Object.prototype 就结束了。
这个时候,我们就可以看到完整的原型链关系图如下:
以上所述就是小编给大家介绍的《JavaScript温故而知新——原型和原型链》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
父与子的编程之旅
桑德 (Warren Sande)、桑德 (Carter Sande) / 苏金国、易郑超 / 人民邮电出版社 / 2014-10-1 / CNY 69.00
本书是一本家长与孩子共同学习编程的入门书。作者是一对父子,他们以Python语言为例,详尽细致地介绍了Python如何安装、字符串和操作符等程序设计的基本概念,介绍了条件语句、函数、模块等进阶内容,最后讲解了用Python实现游戏编程。书中的语言生动活泼,叙述简单明了。 为了让学习者觉得编程有趣,本书编排了很多卡通人物及场景对话,让学习者在轻松愉快之中跨入计算机编程的大门。 第 2 版新增内......一起来看看 《父与子的编程之旅》 这本书的介绍吧!