为什么Object.prototype的__proto__,另一个Object.prototype?
Why is the __proto__ of Object.prototype, another Object.prototype?
如果我们在 chrome 控制台中创建一个数组,
arr=[1,2];
并使用arr.__proto__.__proto__
检查chrome devtools中的原型链,我们得到以下结果。
如您所见,__proto__
对象指向 null,这符合我的逻辑预期。
但是当我尝试访问原型链的同一级别时,即 Object.Prototype
,通过使用 arr.__proto__
,然后搜索下拉菜单,我得到了以下结果。
正如您在突出显示的行中看到的,这次 __proto__
指向另一个 Object.Prototype
。进一步打开后,我得到了与上一个命令相同的内容(查看上一张图片)。
谁能告诉我 Object.prototype
的这个额外层是如何在某些命令中创建的,而在其他命令中却没有?
P.S。我只是在学习原型继承,这是我试图了解它在 JS 环境中是如何实现的。
这是由于 Chrome 开发工具中的一个奇怪行为。 (现已弃用)__proto__
属性 是 getter/accessor 属性,这意味着当它被访问时,它 运行 是代码的一部分。那部分代码看起来像这样:
Object.getPrototypeOf(this); // which returns this[[Prototype]]
上例中的 this
通常是您调用 .__proto__
的对象。例如,如果你做了 arr.__proto__
,那么 this
将是 arr
,所以我们最终得到了预期的 arr
数组的原型。在 Chrome 开发工具控制台中,情况有些不同。而不是在像 arr
这样的对象上调用 getter,而是在您按 (...)
:
时手动调用它
所以现在的问题是 - 在 __proto__
getter 中手动调用 getter 中执行 Object.getPrototypeOf(this);
时 this
的值是多少84=] 开发工具而不是通过 属性 访问权限调用它,例如 arr.__proto__
?这由 Chrome 开发工具团队决定,但它的行为方式似乎是将 this
设置为最初记录的对象 1.在您的第二个示例中,该对象是 arr.__proto__
。结果,getter 最终再次显示 arr.__proto__
的原型,而不是 null
.
下面的代码片段(参见 Chrome 控制台输出)是此行为的一个简单示例:
const obj = Object.create({
get nested() {
console.log("obj === this:", this === obj); // true
console.log("obj[[Prototype]] === this:", this === Object.getPrototypeOf(obj)); // false
return this;
}
}, {
foo: {
value: 'bar',
enumerable: true
}
});
// View chrome console for output
console.log(obj);
在上面的示例中,使用 属性 {foo: "bar"}
创建了一个新对象,该对象的原型设置为具有 getter 的对象 nested() {}
。此 getter returns 并记录 this
的值。当上面的代码是Chrome中的运行时,getter是在obj[[Prototype]]
上点击(...)
调用的(即:obj.__proto__
)nested
属性,你得到以下输出:
上面两个红框代表同一个对象,说明getter里面的this
不是指原型对象(即:{nested: (...)}
)在使用 (...)
调用时,而是指最初记录的对象。与此不同,当您使用 arr.__proto__.__proto__
时,记录的对象是 Object.prototype
,因此当您调用 __proto__
getter 时,this
指的是对象 Object.prototype
,其中 returns null
当它的原型被访问时。
要正确遍历原型链,您可以使用对 Object.getPrototypeOf()
:
的嵌套调用
Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(arr))); // null
1 这只是基于一些观察的假设,但可能不正确 - 我不完全确定 chrome 如何决定设置 this
到,但需要注意的重要一点是 getter 属性 并不总是出现在其中的直接对象。
如果我们在 chrome 控制台中创建一个数组,
arr=[1,2];
并使用arr.__proto__.__proto__
检查chrome devtools中的原型链,我们得到以下结果。
如您所见,__proto__
对象指向 null,这符合我的逻辑预期。
但是当我尝试访问原型链的同一级别时,即 Object.Prototype
,通过使用 arr.__proto__
,然后搜索下拉菜单,我得到了以下结果。
正如您在突出显示的行中看到的,这次 __proto__
指向另一个 Object.Prototype
。进一步打开后,我得到了与上一个命令相同的内容(查看上一张图片)。
谁能告诉我 Object.prototype
的这个额外层是如何在某些命令中创建的,而在其他命令中却没有?
P.S。我只是在学习原型继承,这是我试图了解它在 JS 环境中是如何实现的。
这是由于 Chrome 开发工具中的一个奇怪行为。 (现已弃用)__proto__
属性 是 getter/accessor 属性,这意味着当它被访问时,它 运行 是代码的一部分。那部分代码看起来像这样:
Object.getPrototypeOf(this); // which returns this[[Prototype]]
上例中的 this
通常是您调用 .__proto__
的对象。例如,如果你做了 arr.__proto__
,那么 this
将是 arr
,所以我们最终得到了预期的 arr
数组的原型。在 Chrome 开发工具控制台中,情况有些不同。而不是在像 arr
这样的对象上调用 getter,而是在您按 (...)
:
所以现在的问题是 - 在 __proto__
getter 中手动调用 getter 中执行 Object.getPrototypeOf(this);
时 this
的值是多少84=] 开发工具而不是通过 属性 访问权限调用它,例如 arr.__proto__
?这由 Chrome 开发工具团队决定,但它的行为方式似乎是将 this
设置为最初记录的对象 1.在您的第二个示例中,该对象是 arr.__proto__
。结果,getter 最终再次显示 arr.__proto__
的原型,而不是 null
.
下面的代码片段(参见 Chrome 控制台输出)是此行为的一个简单示例:
const obj = Object.create({
get nested() {
console.log("obj === this:", this === obj); // true
console.log("obj[[Prototype]] === this:", this === Object.getPrototypeOf(obj)); // false
return this;
}
}, {
foo: {
value: 'bar',
enumerable: true
}
});
// View chrome console for output
console.log(obj);
在上面的示例中,使用 属性 {foo: "bar"}
创建了一个新对象,该对象的原型设置为具有 getter 的对象 nested() {}
。此 getter returns 并记录 this
的值。当上面的代码是Chrome中的运行时,getter是在obj[[Prototype]]
上点击(...)
调用的(即:obj.__proto__
)nested
属性,你得到以下输出:
上面两个红框代表同一个对象,说明getter里面的this
不是指原型对象(即:{nested: (...)}
)在使用 (...)
调用时,而是指最初记录的对象。与此不同,当您使用 arr.__proto__.__proto__
时,记录的对象是 Object.prototype
,因此当您调用 __proto__
getter 时,this
指的是对象 Object.prototype
,其中 returns null
当它的原型被访问时。
要正确遍历原型链,您可以使用对 Object.getPrototypeOf()
:
Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(arr))); // null
1 这只是基于一些观察的假设,但可能不正确 - 我不完全确定 chrome 如何决定设置 this
到,但需要注意的重要一点是 getter 属性 并不总是出现在其中的直接对象。