关于Prototype, [[Prototype]], __proto__的区别

对于初学者来说,Prototype 似乎还好理解一些,但是在进行更深入的学习研究之后或许会有点晕,一些文章中 obj.prototype 和 obj.[[prototype]] 中的两种写法区别在哪?分别指的是什么?还有 __proto__ 呢?

一句话解释:

obj.prototype 中的 prototype: 是指类型 (Type) 上的原型对象 (Prototype object)

obj.[[prototype]] 中的 [[prototype]]: 是指实例 (Instance) 中指向创建这个实例的类型上的原型对象的 "链接"

obj.__proto__: 这个属性实际和上面的 [[prototype]] 是同样的东西,在过去被各大浏览器作为非标准属性实现

In Depth:

其实你应该已经猜到了,[[prototype]] 并不是一个真正存在于 obj 或是它的原型链上的一个属性,它存在于 JavaScript 引擎的内部,这样写是为了区分类型上的 prototype 属性和这个实例上的"链接"属性。

在实例上获取原型对象的正确的方式是使用 Object.getProtoTypeOf() 这个在 ECMAScript 5.1 及以后版本的实现中可用,根据 MDN 提供的资料,兼容的浏览器版本为 Chrome 5+, Firefox 3.5+ , Internet Explorer 9+, Safari 5+

而 __proto__ 是一个非标准的属性,由于广泛的支持和使用在 ECMAScript 2015 中被纳入标准,但是这只是作为兼容性考虑,建议使用 Object.getPrototypeOf() 代替

一般像 __proto__ 这样以两个下划线开始的写法为私有属性或私有方法,类似于 CSS 中横线开头为私有前缀

提示:

如果你对性能比较敏感,MDN 文档建议不要更改对象的 [[prototype]] 属性,即使用 obj.__proto__ = xxx 或 Object.setPrototypeOf() 来修改对象的 [[prototype]],这在所有 JavaScript ,因为这会导致一些内部优化失效,造成的性能影响不仅是对于修改 [[prototype]] 的过程,甚至包括任何对于这个修改过的对象的访问。

解决方案是使用 Object.Create() 来创建一个新的对象并设置将要设置为原型对象的对象传入参数中。

发表评论

电子邮件地址不会被公开。 必填项已用*标注