__proto__
你可以使用__proto__
访问对象的内部[[Prototype]]
属性。你可以将[[Prototype]]
视为当前对象在继承层次结构中的实际父级。
prototype
这是一个特殊属性,当设置在(构造函数)函数对象上时,用于为从构造函数创建的实例建立继承链。例如:
function Foo() {}
Foo.prototype = {a: 1}
现在,当你创建一个类型为Foo
的新对象时,新创建的对象的内部[[Prototype]]
属性将引用Foo.prototype
对象。您可以这样确认
console.assert((new Foo()).__proto__ === Foo.prototype);
在您的情况下,
myFunc.prototype = myObj;
你正在创建函数对象上的一个prototype
属性,这仅在使用此函数(构造函数)创建新对象时才会使用。您可以将其视为新对象的模板。因此,当您执行myFunc.a
时,JS引擎尝试在原型链中查找a
在myFunc
及其父级中是否存在,如果没有找到,它就会返回undefined
。
但是,当您执行
myFunc.__proto__ = myObj;
你正在将myFunc
的父级对象在原型链中设置为myObj
。因此,当你执行 myFunc.a
时,JavaScript引擎首先在myFunc
对象本身中查找a
属性,但是在该对象中没有找到这个属性。然后,它尝试在其直接父级中查找,也就是myObj
中查找。这就是为什么在这种情况下它返回1
的原因。
注意:你可以使用以下函数更好地理解原型链。
function printPrototypeChain(object) {
while (object !== null) {
console.log(object);
object = Object.getPrototypeOf(object);
}
}
现在,让我们在将对象设置为函数对象的prototype
属性时打印原型链。
function myFunc() {}
myFunc.prototype = {
a: 1,
b: 2
};
printPrototypeChain(myFunc);
输出结果将是:
[Function: myFunc]
[Function: Empty]
{}
这些对象中没有定义a
,因此返回undefined
。但在这种情况下,
function myFunc() {}
myFunc.__proto__ = {
a: 1,
b: 2
};
printPrototypeChain(myFunc);
原型链就像这样变成了这个样子
[Function: myFunc]
{ a: 1, b: 2 }
{}
并且a
被发现在myFunc
的直接父级中。因此,相应的值1
被返回。
注意:不要在实际代码中使用__proto__
,因为它仅为向后兼容保留在最新版本的JavaScript规范中。在这里了解更多信息。请改用Object.getPrototypeOf
和Object.setPrototypeOf
。
__proto__
一无所知。这意味着它不是标准的一部分,你永远不应该使用它。 - zerkms.prototype
。您是否阅读了 https://dev59.com/4mkw5IYBdhLWcg3wV5ID 的所有答案?您具体没有理解什么(我们很乐意改进它们)? - Bergi