2013-04-18 47 views
3

我有一個問題要問你我們真的必須改爲Object.create嗎?

據我所知,new運營商以這種方式工作

function fakeNew(Ctor) { 
    var instance = Object.create(Ctor.prototype); 
    instance.constructor(); 
    // I skip the conditional for simplicity 
    return instance; 
} 

這一切開始的時候我做了一個Object.create polifill這樣我就可以不使用new創建對象。

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

我開始創建大量objcts和prototiping他們,但很多次話,需要initializa其屬性我做了一個.init()方法把它們

var base = { 
    init: function() { 
    EmitterMixin.call(this); 
    return this; 
    } 
}; 

var obj = Object.create(base).init(); 

但當然,我不得不rembember返回this總是從.init()多次我忘記它或最差,我忘了撥.init()。所以試圖簡化對象初始化,我想創建一個全局幫助器來執行它:調用Object.create,調用初始化函數並返回它。

function create(proto) { 
    var child = Object.create(proto); 
    child.init(); 
    return child; 
} 

當時,當我想打我的頭靠在牆上,當我意識到我在做什麼幾乎被什麼new符不,但慢了很多。而如果polifill適用,我甚至會使用new

所以我問自己,扔什麼好處new?它在主要瀏覽器上爲notably quicker,並且由於JavaScript的性質,我們通常需要調用一個啓動器函數,而不是new開始啓動。

而且最糟糕的,我發現比我用了兩個不同類型的對象的,「抽象」和「實例」,更大的區別是比情況下,我不得不調用.init(),同時附有摘要它不是necesasary因爲他們只會被用作其他物體的原型。我已經看到了在使用new這個模式:

function Foo() { } 
Foo.prototype.method = function() { ... }; 

function Bar() { } 
// "abstract" doesnt invoke initializer 
Bar.prototype = Object.create(Foo.prototype); 
Bar.prototype.other = function() { ... }; 

// "instance", the constructor is called as initializer 
var obj = new Bar(); 

是否真的有益處,如果我們再看到new?我們確定它不是一個更高級別的工具,而是簡化我們必須做的事情嗎? 你看到newObject.create有什麼優點/缺點?

+0

Main [反對'new'的參數](http:// stackoverflow.com/questions/383402/is-javascript-s-new-keyword-considered-harmful)是「被遺忘時會造成多大的傷害」,以及「基於類的繼承太多」 – Bergi

回答

1

我已經嘗試了兩種方法,並且我個人沒有看到使用new的傳統方法的任何問題。 Object.create的主要參數是它使原型繼承更清晰 - 您不必瞭解函數構造函數的prototype屬性的複雜性以及它如何與對象的實際原型相關。但它確實要求初始化是一個單獨的步驟。

我的首選方法是結合兩種方法,例如,:

function Animal(name) { 
    this.name = name || null; 
} 
Animal.prototype.eat = function() { 
    console.log('yum'); 
} 

function Cat(name) { 
    Animal.call(this, name); 
} 
Cat.prototype = Object.create(Animal.prototype); 
Cat.prototype.constructor = Cat; 

Cat.prototype.meow = function() { 
    console.log('meow'); 
} 

var garfield = new Cat('garfield'); 
garfield.eat(); 
garfield.meow(); 

Object.create是繼承更好地在這裏比Cat.prototype = new Animal()有兩個原因:

  1. 如果你想要求name參數(投擲如果沒有通過它的一個例外),你可以這樣做和繼承(Cat.prototype = Object.create(Animal.prototype))仍然有效。
  2. 如果您忘記從Animal構造函數中調用Cat的構造函數,那麼Animal構造函數創建的所有屬性都將被定義爲undefined,從而使您能夠快速發現錯誤。

雖然這種方法(使用構造函數和new)小於「純粹」的原型,它仍然是原型繼承並且只要你知道如何使用它正確的它工作得很好,需要多一點的打字少Object.create方法。

我在我的Javascript OO庫文檔simpleoo的文檔中寫了一些關於此的其他說明。 (注意:我可能會很快爲該庫更改API;我正在鏈接到它,主要是因爲文檔更詳細地討論了其中一些概念。)

相關問題