2013-03-05 66 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

相關問題