JavaScript原型、原型链知识回顾
前言
原型和原型链是 JavaScript 中非常重要的一个知识点。
前置知识
构造函数
构造函数在面向对象的语言中,通常是用来创建实例对象。在 ES6 版本前,JavaScript 中使用 function 来模拟类。
function Person(name, age) {
this.name = name;
this.age = age;
}实例
借助构造函数,使用 new 的方式来创建一个实例。
var p = new Person('James', 24);原型、原型链
原型是构造函数上的一个属性,称为 prototype,属性值是一个对象。
Person.prototype
构造函数、原型和实例之间的关系
每个构造函数都有一个原型对象,原型有一个属性指回构造函数,而实例有一个内部指针指向原型。如果原型是另一个类型的实例呢?那就意味着这个原型本身有一个内部指针指向另一个原型,相应地另一个原型也有一个指针指向另一个构造函数。这样就在实例和原型之间构造了一条原型链。这就是原型链的基本构想。 –《JavaScript 高级程序设计第 4 版》 第 8 章原型链部分
接下来,结合例子来理解上面的这段话:
function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function() {
returnthis.property;
};
function SubType() {
this.subproperty = false;
}
// 继承 SuperType
SubType.prototype = newSuperType();
SubType.prototype.getSubValue = function() {
returnthis.subproperty;
}
let instance = new SubType();
console.log(instance.getSuperValue())每个构造函数都有一个原型对象。
SuperType.prototype
SubType.prototype
原型对象有一个 constructor 属性指回构造函数。
SuperType.prototype.constructor
SubType.prototype.constructor
这里留个疑问。为什么 SubType 原型上的 constructor 属性是指向 SuperType 呢?这里就涉及到原型链的概念。
实例有一个内部指针
__proto__指向原型 prototype。
instance.__proto__ === SubType.prototype
instance.__proto__ === SuperType.prototype
如果原型 A 是另一个类型 B 的实例,则按照第 3 点的描述,则该原型 A 会的 __proto__ 会指向原型 B 的 prototype。 按照上述列子,则有
// SubType 的原型是 SuperType 的实例
SubType.prototype = new SuperType();
SubType.prototype.__proto__ === SuperType.prototype
SuperType 原型的 __proto__ 属性指向了 Object.prototype

通过实例的 __proto__ 与构造函数原型对象 prototype 的指向关系,就形成了原型链。借助原型链,我们可以在原型链上查找实例属性和原型上的方法
回到步骤 3 的疑问,为什么 SubType.prototype.constructor 是指向 SuperType 呢?
constructor是原型上的属性- 未修改
SubType.prototype原型前,SubType.prototype上是constructor是指向本身的构造函数的

- 在
SubType.prototype = new SuperType()执行后。原型对象变成了SuperType的实例。实例的constructor属性是指向构造函数的。当我们使用SubTyper.prototype.constructor访问构造函数时,实际上便是在原型链上进行了查找。整个查找过程如下:首先查找Subtype.prototype有没有 constructor 属性。由于它已经是SuperType的实例了。实例上没有找到constructor属性,就会去原型上找,最后在SuperType上面找到了。所以,SubType.prototype.constructor指向的是SuperType.
总结
- 构造函数都有一个原型对象
prototype,构造函数也属于对象。 - 对象都有一个
__proto__属性,指向它的原型。 - Object 原型是原型链的终点,因为
Object.__proto__ === null。 - 原型对象上有一个
constructor属性,指向原型对应的构造函数。
