原型、原型链知识回顾

时间:2021-2-20 作者:admin

前言

原型和原型链是 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 () {
    return this.property;
};

function SubType () {
    this.subproperty = false;
}

// 继承 SuperType
SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function () {
    return this.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 呢?

  1. constructor 是原型上的属性

  2. 未修改 SubType.prototype 原型前,SubType.prototype 上是 constructor 是指向本身的构造函数的

  1. 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 属性,指向原型对应的构造函数。
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。