2015-04-26 130 views
5

原型繼承的這兩個實現之間有什麼區別,並且考慮到我們正在處理2個不同的「原型」(原型屬性僅針對函數和內部原型),以及這些實現在原型中有何不同鏈查找?另外,第一個實現(使用prototype屬性)是否依賴於我們使用new運算符?這兩個原型繼承的實現有什麼區別?

分配給一個功能的prototype財產,並使用new操作者:

function foo() {} 

foo.prototype.output = function(){ 
    console.log('inherits from Function.prototype property'); 
}; 

bar = new foo(); 
bar.output(); 

存儲在對象文本的函數,並使用Object.create()方法:

var foo = { 
    output: function(){ 
    console.log('inherits from the internal prototype'); 
    } 
}; 

var bar = Object.create(foo); 
bar.output(); 
+0

一個區別是,'Object.create'較新,且在IE8不支持以下 – keune

+0

我看不出原型** **繼承您的例子。 – hindmost

+0

@最後可以詳細說明一下嗎? – shmuli

回答

3

的主要區別它的使用方式以及相關的危險。

第一個強制您在創建新對象時使用new。語法相當醜陋(SomeConstructor.prototype.method),它有一個主要缺陷:調用構造函數(this.name = nameParam ...)而不使用new將構造函數應用於全局對象。構造函數的行爲很奇怪(創建一個代表SomeConstructor.prototype的新對象,然後將構造函數應用到新對象,然後如果構造函數返回某個東西來替換對象的東西)。此外,在您的示例中,foo本身不可用,您必須創建一個新對象才能訪問其功能。

第二個,Object.create,不強制你使用任何syntoxic怪癖。你沒有全球污染風險。對象foo具有已經可以在不創建新對象的情況下使用的功能,並且bar將簡單借用這些功能。這種模式還可以更容易地實施工廠(如果不需要,則不需要使用new)和對象池。

Eric Eliott talks about it very wellKyle Simpson wrote a whole book關於原型代表團!

現在,這裏的查詢是如何發生的:

  • 用構造,查找上Constructor.prototype(未構造的實際內部樣機完成,但其prototype財產如果你覺得困惑。 ,恭喜,你是人類)。其他屬性在構造函數中設置。 foo本身不用於查找,foo.prototype(再次,不同於指向Function的foo.__proto__)是用於它的那個。
  • With Object.create查找是在對象本身上完成的(foo)。對象上沒有prototype非原型屬性。

還有very funny diagrams on this page of Kyle Simpson's book這說明了這一點。

更多new在這樣一個問題:Is JavaScript's "new" keyword considered harmful?

+1

嚴格模式解決了全球污染問題。 – jdphenix

+0

@Kyll與「lookup」有什麼不同?這些實現使用2個不同的'prototype'對象,不是嗎? – shmuli

+0

讓我編輯! –

-1

第一個例子 - FOO,是一個函數。

第二個例子 - foo是一個對象。

在第二個例子中,bar變成了一個沒有構造函數的新實例。 請參閱 - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/create,添加構造函數。

作爲一個方面說明,通常的最佳實踐是構造函數應該以大寫字母開頭。

1

OK,首先,如果你不知道,Object.create是基於由Douglas Crockford的提出了以下模式(閱讀更多here):

function create (proto) { 
    function f() {} 
    f.prototype = proto; 
    return new f(); 
} 

現在,你必須知道的是,如果您通過null作爲參數,上面的代碼不會產生相同的結果。
用於創建新對象的ECMAScript算法(閱讀更多here)指出,如果函數的原型設置爲null(或任何非對象),則當您嘗試使用new f()語法時,新創建的對象將從Object.prototype
如果使用Object.create(null),新創建的對象都將有[[Prototype]]內部成員設置null,這意味着原型鏈將停在那裏(你的對象沒有得到hasOwnPropertyObject.prototype其他的東西,正常的對象會)。

var o1 = create(null); 
var o2 = Object.create(null); 
Object.getPrototypeOf(o1) === Object.prototype // true 
Object.getPrototypeOf(o2) === Object.prototype // false 
Object.getPrototypeOf(o2) === null // true