如果我们在 Chrome 控制台中创建一个数组,
arr=[1,2];
并使用
arr.__proto__.__proto__
检查 chrome devtools 中的原型链,我们得到以下结果。
正如你所看到的,
__proto__
对象指向null,这是我逻辑上所期望的。
但是当我尝试使用 Object.Prototype
访问原型链的同一级别,即 arr.__proto__
,然后搜索下拉菜单时,我得到了以下结果。
正如您在突出显示的行中看到的,这次
__proto__
指向另一个 Object.Prototype
。进一步打开它,我得到了与上一个命令相同的内容(检查上一张图片)。
有人可以告诉我这个额外的
Object.prototype
层是如何在某些命令中创建的,而不是在其他命令中创建的吗?
附注我刚刚学习原型继承,这是我尝试了解它在 JS 环境中是如何实现的。
这是由于 Chrome 开发工具中的奇怪行为造成的,其中
__proto__
getter 将访问原始记录对象的 [[Prototype]]
,无论对象的嵌套程度如何。在 JavaScript 中,(现已弃用) __proto__
属性是一个 getter,这意味着当它被访问时,它会运行一部分代码。这部分代码看起来像这样:
Object.getPrototypeOf(this); // which returns this[[Prototype]]
上例中的
this
通常是您调用 .__proto__
的对象。例如,如果您执行了 arr.__proto__
,那么 this
将是 arr
,因此您最终会按预期获得 arr
数组的原型。在 Chrome 开发工具控制台中,情况有些不同。 getter 不是在像 arr
这样的对象上调用的,而是当您按 (...)
时手动调用:
所以现在的问题是 - 当手动调用
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,您将得到以下输出:
在上面,两个红色框代表 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 属性出现的直接对象。