打印原型链的源对象可以是多种多样的:
[1, 2, 3]
// 数组文字{a: 1}
// 对象字面量new Set()
// 内置集合new Promise( () =>{} )
// 内置 Promisefunction foo(){}
// 函数作为对象window
// 来自 DOM 的全局窗口对象实际上,任何物体都可以。
我的期望是这个表达式总是正确的:
anyObject.constructor.prototype === Object.getPrototypeOf(anyObject)
这里是打印原型链和链上每个对象的构造函数的代码,以及详细说明该构造函数指向何处的提示。
function chain(o) {
while (o) {
console.dir(o);
let tip = '';
if (o.constructor.prototype === Object.getPrototypeOf(o))
tip = 'points to the next object on the chain, i.e. its [[prototype]].';
else if (o.constructor.prototype === o)
tip = 'points to the above object itself.';
else tip = 'NEVER EXECUTED TO HERE';
console.log('Its constructor:', o.constructor, tip)
o = Object.getPrototypeOf(o);
}
}
结果示例:
根据结果我们可以发现,并不是链上的每个对象都如我所料。
如何理解这个设计?
我的期望是这个表达式总是正确的:
anyObject.constructor.prototype === Object.getPrototypeOf(anyObject)
这种期望根本就是错误的。
const constructor = {prototype: null};
const prototype = {constructor};
constructor.prototype = prototype;
是一个简单的例子,其中
prototype.constructor.prototype
指向 prototype
本身,与 Obect.getPrototypeOf
检查的原型链无关。
实际上,这个循环引用几乎可以在 any 类的
any
.prototype
对象上找到,无论是 (class {}).prototype
、Array.prototype
或 Function.prototype
。
您的期望仅适用于继承其
.constructor
属性的实例,其 .prototype
又指向实例的 [[prototype]]。