2015-07-10 67 views
7

从我所知道的函数应该继承其prototype对象的属性,可以使用.prototype__proto__属性访问属性。__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,但无法弄清楚。

+2

http://es5.github.io/完全不了解'__proto__'。这意味着它不是标准的一部分,你不应该使用它。 – zerkms

+0

不,对象的原型(带有它的那个继承自)不是**'.prototype'。你读过所有的答案http://stackoverflow.com/questions/9959727/proto-vs-prototype-in​​-javascript?你不明白什么(我们很乐意改进它们)? – Bergi

+0

那么什么是.prototype用于? – Flake

回答

15

__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引擎试图在myFunc及其父母的原型链中找到a,并且它没有找到它,这就是为什么它返回undefined

但是,当你做

myFunc.__proto__ = myObj; 

您设置的myFunc父,在原型链,myObj。所以,当你做myFunc.a时,JS引擎首先试图在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 } 
{} 

amyFunc的直接父被发现。因此,返回相应的值1

注意:不要在您的实际代码中使用__proto__,因为它保留在最新版本的JavaScript规范中,仅用于向后兼容。详细了解它here。改为使用Object.getPrototypeOfObject.setPrototypeOf

+1

两个函数的原型...... dats令人困惑!!! – Flake

+0

当你做myFunc.prototype = myObj; myObj可用于myFunc实例,不适用于myFunc。 var x = new myFunc(); console.log(x.a); //返回1 – prgmrDev

0

你很混淆myFunc,这是一个构造函数,实例myFunc

如果你做这样的事情:

var o = new myFunc(); 
alert(o.a); 

它会提醒1,因为omyFunc一个实例,因此其a财产来自myFunc原型。

如果你设置了__proto__,你可以直接替换掉以前继承的函数原型,并用你的原型对象替换原型。事实上,在这样做之后,您可以在myFunc上找不到通常用于功能的任何方法,例如call

myFunc.__proto__ = myObj; 
myFunc.call(null); // Will throw an error 
0

所有JS对象都有__proto__系统属性。如果您尝试获取对象a的物件x的值,首先会在物件a属性中搜索此属性。如果没有发现该物业将被搜索a.__proto__性能。等等。 这就是为什么myFunc.a ruturns 1在你的例子。 当您设置myFunc.prototype=myObj这意味着myObj将在未来使用,当你创建的myFunc实例:

var mf = new myFunc(); 

,并且并不意味着myFunc必须a protpery本身,正如我上面提到。

相关问题