为什么Object.prototype的__proto__是另一个Object.prototype?

问题描述 投票:0回答:1

如果我们在 Chrome 控制台中创建一个数组,

arr=[1,2];

并使用

arr.__proto__.__proto__
检查 chrome devtools 中的原型链,我们得到以下结果。 enter image description here

正如你所看到的,

__proto__
对象指向null,这是我逻辑上所期望的。 但是当我尝试使用
Object.Prototype
访问原型链的同一级别,即
arr.__proto__
,然后搜索下拉菜单时,我得到了以下结果。 enter image description here

正如您在突出显示的行中看到的,这次

__proto__
指向另一个
Object.Prototype
。进一步打开它,我得到了与上一个命令相同的内容(检查上一张图片)。

有人可以告诉我这个额外的

Object.prototype
层是如何在某些命令中创建的,而不是在其他命令中创建的吗?

附注我刚刚学习原型继承,这是我尝试了解它在 JS 环境中是如何实现的。

javascript inheritance google-chrome-devtools prototype prototypal-inheritance
1个回答
7
投票

这是由于 Chrome 开发工具中的奇怪行为造成的,其中

__proto__
getter 将访问原始记录对象的
[[Prototype]]
,无论对象的嵌套程度如何。在 JavaScript 中,(现已弃用)
__proto__
属性是一个 getter,这意味着当它被访问时,它会运行一部分代码。这部分代码看起来像这样:

Object.getPrototypeOf(this); // which returns this[[Prototype]]

上例中的

this
通常是您调用
.__proto__
的对象。例如,如果您执行了
arr.__proto__
,那么
this
将是
arr
,因此您最终会按预期获得
arr
数组的原型。在 Chrome 开发工具控制台中,情况有些不同。 getter 不是在像
arr
这样的对象上调用的,而是当您按
(...)
时手动调用:

Image showing how an ellipsis icon can be pressed for the proto getter property

所以现在的问题是 - 当手动调用

this
getter 时,执行
Object.getPrototypeOf(this);
__proto__
的值是多少?这由 Chrome 开发工具团队决定,但它的行为方式似乎是将
this
设置为最初记录的对象1。在第二个示例中,该对象是
arr.__proto__
。结果,吸气剂最终再次显示
[[Prototype]]
arr.__proto__
,而不是
null

下面的代码片段(请参阅 Chrome 控制台输出)是此行为的一个简单示例:

const obj = {foo: 'bar'};
const prototypeObj = {
  get fake__proto__() {
    console.log("obj === this:", this === obj); // true: Means that `this` still refers to the original object, even when fake__proto__ is invoked on [[Prototype]] object in the console
    console.log("obj[[Prototype]] === this:", this === Object.getPrototypeOf(obj)); // false: Shows that `this` inside of fake__proto__ isn't the prototype object, even when `fake__proto__()` is invoked on the `[[Prototype]]` object.
    return this;
  }
};

Object.setPrototypeOf(obj, prototypeObj); // Note: setPrototypeOf isn't recommended to do, but is being used here for example purposes only

// View chrome console for output
console.log(obj);

在上面的代码片段中,创建了一个新对象

{foo: "bar"}
,并将其
[[Prototype]]
设置为带有名为
fake__proto__() {}
的 getter 的对象。这个 getter 用于查看调用时
this
的值是什么,以便我们可以了解本机
__proto__
getter 可能使用的内容。当上面的代码在 Chrome 中运行时,通过单击
(...)
上的
obj[[Prototype]]
来调用 getter,您将得到以下输出:

image to show that the fake__proto__ getter logs the original object for this even for the nested [[Prototype]] object

在上面,两个红色框代表 same 对象,表明 getter 内部的

this
在使用
[[Prototype]] 上的 
(...)
 调用时并不引用设置为 
[[Prototype]]
 的对象
对象,而是指最初记录的对象。

与此不同的是,当您使用

arr.__proto__.__proto__
时,记录的对象是
Object.prototype
,因此当您调用
__proto__
getter 时,
this
引用对象
Object.prototype
,当其原型为 时,它会返回
null
已访问。

要正确遍历原型链,您可以使用嵌套调用

Object.getPrototypeOf()

Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(arr))); // null

1 这只是基于一些观察的假设,但可能不正确 - 我不完全确定 chrome 如何决定将

this
设置为什么,但需要注意的重要一点是它不是始终是 getter 属性出现的直接对象。

© www.soinside.com 2019 - 2024. All rights reserved.