fn.[[Prototype]].[[Prototype]].__proto__ 为什么是 Fn.prototype ?

最近在学习原型和原型链。在控制台里,我遇到了一些不解的现象,代码如图

对于这个__proto__有些看不明白,为什么不是null,而是Fn的prototype。
而我打印 fn.__proto__.__proto__.__proto__ 的结果是我预想的 null。

阅读 588
avatarAI BotBETA

在 JavaScript 中,每个对象都有一个内部链接,称为 [[Prototype]],它指向另一个对象,即该对象的原型。当试图访问一个对象的属性时,如果该对象自身没有这个属性,那么 JavaScript 会在该对象的原型(即 [[Prototype]] 指向的对象)上查找这个属性,这就是原型链的概念。

然而,由于 [[Prototype]] 是一个内部链接,JavaScript 为开发者提供了一个非标准的、但在大多数环境中可用的访问器属性 __proto__,用于读取和设置 [[Prototype]]

对于你的问题,fn 是一个函数对象,它的 __proto__ 指向 Function.prototype,这是因为所有的函数对象都继承自 Function.prototype。你可以通过 fn.__proto__ === Function.prototype 来验证这一点。

当你打印 fn.__proto__.__proto__ 时,你实际上是在查看 Function.prototype 的原型。在 JavaScript 中,Function.prototype 的原型是 Object.prototype,因此 fn.__proto__.__proto__ 指向 Object.prototype

至于 fn.__proto__.__proto__.__proto__ 为何是 null,这是因为 Object.prototype 的原型是 null。在 JavaScript 中,原型链的尽头是 null,表示原型链的结束。

总结一下,__proto__[[Prototype]] 的关系是:__proto__ 是用于访问和设置 [[Prototype]] 的非标准属性。它们之间的关系就像是一个公开的(__proto__)和一个私有的([[Prototype]])接口。

至于为什么在这一层突然没有 [[Prototype]] 而出现了 __proto__,这实际上是因为 __proto__Object.prototype 的一个属性,而 Object.prototype 本身就是一个对象。所以,当你访问 fn.__proto__.__proto__ 时,你实际上是在访问一个对象(即 Object.prototype),而这个对象有自己的 __proto__ 属性。然而,Object.prototype 的原型是 null,所以 Object.prototype.__proto__null

请注意,虽然 __proto__ 在许多环境中都可用,但它并不是 JavaScript 的标准属性,因此不建议在生产代码中使用。在需要操作原型链时,应该使用 Object.getPrototypeOf()Object.setPrototypeOf() 方法。

2 个回答

这个跟展示的方法有关。因为 __proto__ 不是一个普通的属性,而是一个定义在 Object.prototype 上的 accessor property/属性访问器 。(你可以在 __proto__ 下面看到 get __proto__ , set __proto__)

所以 __proto__ 并没有出现在每一层 prototype 里,而只出现在了它所定义的位置(Object.prototype.__proto__),而它的值展示的是它在原始对象(也就是 Fn)上的计算结果,也就是 Fn.prototype 。

[[Prototype]] 是真正的原型对象。但是 Object.prototype.[[Prototype]] 是 null ,于是在结果中并没有展示。


[[Prototype]] 也不是普通的属性,而是一个 internel slot 。它在调试器里的展示策略可能跟普通的属性也不一样。

fn是构造器Fn的一个实例,故fn的原型指向Fn.prototypeObject.getPrototypeOf(fn) === Fn.prototype,在getPrototypeOf这个标准API出来之前浏览器通过__proto__这样一个属性来访问对象的原型,所以fn.__proto__ === Fn.prototype

Fn.prototype是一个对象,所以你可以Fn.prototype.sayHello = function(){},对象的构造器就是Object,通常定义一个对象都是使用字面量{prop: 'value'}但是其实对象也是可以通过构造器new出来的,即new Object(),所以对象的原型({}).__proto__ === Object.prototype

fn.__proto__.__proto__.__proto__翻译就是fn的原型的原型的原型,也就是网上找三次构造器的prototype:
1.fn原型Fn.prototype;
2.Fn.prototype原型Object.prototype;
3.Object.prototype原型null

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏