据我所知,函数应该从其原型对象继承属性,可以使用.prototype或__proto__属性访问它们.
//my prototype Object var myObj = { a: 1,b: 2 }; var myFunc = function () {}; // setting function's `prototype` property myFunc.prototype = myObj; alert(myFunc.a); //returns undefined (Why???) I was expecting 1
但当我尝试以下,
//setting function __proto__ property myFunc.__proto__ = myObj; //returns 1 alert(myFunc.a);
那么为什么当我设置myFunc .__ proto__而不是我设置myFunc.prototype时它会起作用?
我确实参考了__proto__ VS. prototype in JavaScript,但无法弄清楚.
解决方法
您实际上可以使用__proto__访问对象的内部[[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引擎会尝试在原型链中找到myFunc及其父项,并且它找不到它,这就是它返回undefined的原因.
但是,当你这样做的时候
myFunc.__proto__ = myObj;
您正在将原型链中的myFunc的父级设置为myObj.因此,JS引擎首先尝试在myFunc对象中找到一个,而它不在那里.所以,它试图在它的直接父母中找到它,这是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] {}
这些对象都没有定义,因此返回undefined.但是,在这种情况下,
function myFunc() {} myFunc.__proto__ = { a: 1,b: 2 }; printPrototypeChain(myFunc);
原型链变成这样
[Function: myFunc] { a: 1,b: 2 } {}
和a在myFunc的直接父母中找到.因此,返回相应的值1.
注意:不要在实际代码中使用__proto__,因为它仅为了向后兼容性而保留在最新版本的JavaScript规范中.了解更多信息here.请改用Object.getPrototypeOf
和Object.setPrototypeOf
.