__proto__和原型差异

Fla*_*ake 8 javascript inheritance prototype function

据我所知,函数应该从其prototype对象继承属性,可以使用.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
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试以下,

//setting function __proto__ property
myFunc.__proto__ = myObj;
//returns 1
alert(myFunc.a);
Run Code Online (Sandbox Code Playgroud)

那么为什么它在我设置myFunc.__proto__时起作用而不是在我设置时起作用myFunc.prototype

我确实参考了__proto__ VS. JavaScript中的原型但无法弄清楚.

the*_*eye 16

__proto__

您实际上可以使用访问[[Prototype]]对象的内部属性__proto__.您可以将其[[Prototype]]视为继承层次结构中当前对象的实际父级.

prototype

当在(构造函数)函数对象上设置时,这是一个特殊属性,用于为从构造函数创建的实例建立继承链.例如,

function Foo() {}
Foo.prototype = {a: 1};
Run Code Online (Sandbox Code Playgroud)

现在,当您创建一个新类型的对象时Foo,新创建的对象的内部[[Prototype]]属性将引用该Foo.prototype对象.你可以这样确认

console.assert((new Foo()).__proto__ === Foo.prototype);
Run Code Online (Sandbox Code Playgroud)

在你的情况下,

myFunc.prototype = myObj;
Run Code Online (Sandbox Code Playgroud)

您正在prototype函数对象上创建一个属性,这将仅在您使用此函数创建新对象时使用(构造函数).您可能希望将其视为新对象的模板.所以,当你这样做myFunc.a,JS引擎试图找到amyFunc和它在原型链的父母,并没有找到它,这就是为什么它返回undefined.

但是,当你这样做的时候

myFunc.__proto__ = myObj;
Run Code Online (Sandbox Code Playgroud)

您正在设置myFunc原型链中的父项myObj.所以,当你这样做时myFunc.a,JS引擎首先尝试amyFunc对象本身中找到它,但它并不存在.所以,它试图在它的直接父母中找到它,也就是说myObj.这就是它1在这种情况下返回的原因.


注意:您可以使用以下函数更好地理解原型链

function printPrototypeChain(object) {
    while (object !== null) {
        console.log(object);
        object = Object.getPrototypeOf(object);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,让我们在将对象设置为prototype函数对象的属性时打印原型链.

function myFunc() {}
myFunc.prototype = {
    a: 1,
    b: 2
};
printPrototypeChain(myFunc);
Run Code Online (Sandbox Code Playgroud)

输出将是

[Function: myFunc]
[Function: Empty]
{}
Run Code Online (Sandbox Code Playgroud)

这些对象都没有a定义,因此undefined返回.但是,在这种情况下,

function myFunc() {}
myFunc.__proto__ = {
    a: 1,
    b: 2
};
printPrototypeChain(myFunc);
Run Code Online (Sandbox Code Playgroud)

原型链变成这样

[Function: myFunc]
{ a: 1, b: 2 }
{}
Run Code Online (Sandbox Code Playgroud)

并且a是在myFunc直系亲属中找到的.因此,1返回相应的值.

注意:请勿__proto__在实际代码中使用,因为它仅为了向后兼容性而保留在最新版本的JavaScript规范中.在这里阅读更多相关信息.使用Object.getPrototypeOfObject.setPrototypeOf替代.