[JS]原型链

347 阅读4分钟

原型链

原型链是JS中十分重要的一个概念,今天的文档就选这个主题(其实已经准备了好一会了这篇)

首先通过一张图来大概了解一下原型链 原型链.jpg

假设这是一个RPG游戏,在你创建人物的时候,可以选择创建一个角色并且指定传承了几代,传承二代的角色(变量X)将会在出生时获得一把剑和一个盾牌,而传承三代的角色(变量Y)将会在出生时获得一把剑,一个盾牌以及一个飞镖。

也许这张图初看之下有些懵逼,但不要着急,我们先往下看,看完之后再来回头看这张图。一定要回头看!!

什么时候需要讨论到原型链?

这里提供一段MDN站点上的释义,(用中文来读这个的时候,我总觉得很绕,捋不清__proto__prototype下面提供一段中英双版本)

MDN上提供的中文版本:

当谈到继承的时候。

当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象(object)都有一个私有属性(称之为 __proto__ )指向它的构造函数的原型对象(prototype)。

MDN上提供的英文版本(附逐句翻译):

When it comes to inheritance, JavaScript only has one construct: objects.

当谈到继承的时候,JS只有一种结构:对象。

Each object has a private property which holds a link to another object called its prototype.

每个对象都有一个私有属性,用于保持对另一个对象的链接,这个对象称为它的 prototype

That prototype object has a prototype of its own, and so on until an object is reached with null as its prototype.

这个作为prototype的对象也有一个自己的prototype,如此这般直到到达一个将null作为它的prototype的对象。

什么是__proto__

以上,我们得到以下两点结论:

  1. __proto__为对象的私有属性,顺着它一直到达null的这一过程称之为原型链(因为它由一个个原型链接而成)(a link to another object called its prototype)
  2. 在这里我们还未得到属性prototype的定义

什么是prototype

紧接上文,我们首先来解决属性prototype的定义问题。在不同的浏览器中,原型属性(__proto__)有不同的实现方式,一般的浏览器中我们能看到的原型属性被记为[[Prototype]]。即它们的含义是一样的。但是这区别于构造函数 funcprototype 属性。

关于构造函数的prototype属性,这是我在ECMAScript 1st Edition (ECMA-262)规范文档中得到的解释(附逐句翻译):

A prototype is an object used to implement structure, state, and behavior inheritance in ECMAScript.

原型是 ECMAScript用于实现结构、状态、行为继承的对象。

When a constructor creates an object, that object implicitly references the constructor’s associated prototype for the purpose of resolving property references.

当构造函数创建一个对象时,该对象隐式引用了构造函数的关联原型,用于解析属性引用。(PS:这一段我还有些似懂非懂)

The constructor’s associated prototype can be referenced by the program expression constructor.prototype,

[重点]构造函数的关联原型会被程序表达式constructor.prototype引用

and properties added to an object’s prototype are shared, through inheritance, by all objects sharing the prototype.

共享该原型的所有对象通过继承,共享添加到原型对象上的属性

而关于prototype属性的其他内容可以参看ECMA的相关文档。

以上,我们得到了这些结论:

  1. prototype属性是Function的特有属性
  2. prototype属性会引用构造函数的关联原型
  3. prototype属性还包含其它一些内容

在浏览器控制台中一探

首先我们创建一个对象,基于继承的环境,我们使用new方式进行变量声明

const NUM = new Number(1);

然后观察一下这个NUM

NUM_1.jpg

也许你已经发现了,说好的__proto__属性没看到,关于这点请看以下解释:

遵循ECMAScript标准,someObject.[[Prototype]] 符号是用于指向 someObject 的原型。从 ECMAScript 6 开始,[[Prototype]] 可以通过 Object.getPrototypeOf()Object.setPrototypeOf() 访问器来访问。这个等同于 JavaScript 的非标准但许多浏览器实现的属性 __proto__

但它不应该与构造函数 funcprototype 属性相混淆。被构造函数创建的实例对象的 [[Prototype]] 指向 funcprototype 属性。Object.prototype 属性表示 Object 的原型对象。

所以,只是虚惊一场,我们的探索之旅虽然遇到了[障眼法]。

NUM原型链.jpg

当我们的脚步来到此处,请回想以下关键词,然后回去看文章一开始的那张图解。

继承

prototype(原型)

__proto__([[Prototype]])

prototype&&__proto__小结

function 拥有 prototype__proto__

其他对象拥有__proto__

关于原型链就先写到这里,指正和补充请不吝赐教。

参考资料:

[MDN文档]  developer.mozilla.org/zh-CN/docs/… 

[网络博客]  www.cnblogs.com/jayfeng/p/1… 

\