2013-03-05 76 views
5

我很新使用object.create而不是传统的js方式来实现原型继承。Object.create设置__proto__但不是原型

在Chrome中,至少我很惊讶地看到下面的代码:

var baseObject = { 
test : function(){ 
    console.log('Child'); 
} 
} 

var newObject = Object.create(baseObject); 
newObject.test = function(){ 
console.log('Parent'); 
this.__proto__.test(); 
} 
console.log(newObject); 

newObject.test(); 

产生以下(模拟的Web工具的输出):

Object {test: function, test: function} 
    test: function(){ 
    __proto__: Object 
     test: function(){ 
     __proto__: Object 
Parent 
Child 

所以你看它不设置原型,但而不是只有“__proto__”,我认为它的使用是不鼓励的。你可以看到,在我的代码中,我可以正确地继承,并调用父对象,但只能使用“__proto__”。使用“原型”会导致错误(未定义)。

这是怎么回事吗?我想object.create会设置“原型”,因为这是标准(或我所假设的)。为什么填充并使我使用“__proto__”

回答

5

没有使用__proto__设置您的原型继承是不鼓励的,因为它是非标准的。这并不意味着您不能使用Object.create()来创建具有特定原型对象的新对象。

对象缺省情况下没有.prototype属性。你混淆了函数的.prototype对象。

所以,如果我有这样的功能:

function Foo() { 

} 

Foo函数对象都有一个.prototype属性引用时作为构造函数调用,将被用作创建的任何对象的__proto__的对象。

var f = new Foo(); 

所以现在f是在其原型链的Foo.prototype的对象。您可以使用Object.getPrototypeOf()进行验证;

Object.getPrototypeOf(f) === Foo.prototype; // true 

什么Object.create给你是要建立相同的原型链的能力,但不使用一个构造函数。所以这是相同的。

var f2 = Object.create(Foo.prototype); 

现在我们有一个对象,它的设置方式与原始的f对象相同。

Object.getPrototypeOf(f2) === Foo.prototype;   // true 
Object.getPrototypeOf(f2) === Object.getPrototypeOf(f); // true 

所以这是做什么最终是同样的事情只是用不同的方式。对象与其原型链之间的关系是内部的关系。非标准的__proto__只是暴露了这种关系。

+0

非常有趣。你是对的,我忘了原型只适用于功能。所以基本上,至少是铬,使用__proto__类型的复制原型以非标准方式用于计划对象? – nahelm 2013-03-05 21:44:12

+0

@nahelm:排序。 '__proto__'可以让你给现有的对象一个新的原型链。构造函数和Object.create只是让你在创建对象时进行设置。从那里它是永久的。事实上,如果你从构造函数中创建一个对象,那么你给构造函数一个新的'.prototype'对象,你创建的对象仍然会引用原始对象。它永远不会改变。 – 2013-03-05 21:47:13

+0

我想我终于明白了。我的一部分困惑是,我期望我的网络工具在Chrome中显示我创建的对象的原型。我也想过一些愚蠢的理由,即使用new关键字可以使用prototype关键字(在你的例子中是f.prototype),这是不正确的。当我做了你的Foo例子并在其原型中添加了一个函数时,当我使用console.log(f)时,该函数也显示在__proto__对象中。因此,本质上__proto__暴露了通常隐藏的原型链,正如您所说的永久链接。 – nahelm 2013-03-06 22:07:46

0

实例的__proto__属性应该是一样的构造的prototype财产。

当创建一个对象,其__proto__属性被设置为引用相同的对象作为其内部[[Prototype]](即它的构造的prototype对象)。为__proto__分配新值也会更改内部[[Prototype]]属性的值,但对象不可扩展的地方除外。

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/proto#Description

+0

尽管在这种情况下,由于原始对象是一个对象,构造函数的原型是对象。结果'constructor.prototype!= __proto__'。 – 2013-03-05 21:18:38

0

Object.create()设置原型为该特定对象实例。 prototype是对构造函数的一个属性,它是对象自动为通过使用该构造函数使用new运算符创建的每个实例的[[Prototype]]指定的属性。

__proto__是访问特定实例的[[Prototype]]的非标准方法。您也可以拨打Object.getPrototypeOf(this)以获取原型的标准方式。

+1

可能想要将“原型”更改为“[[Prototype]]”以澄清您何时谈论内部属性。 – 2013-03-05 21:18:44

+0

@MattBall谢谢! – Brandon 2013-03-05 21:26:55