2013-08-28 22 views
2

我與面向對象的JavaScript,以處理有不同的屬性,但相同的方法多個對象的常用方法有限的經驗將被使用構造如下:複製構造函數和新用的Object.create()

function Animal (type) { 
    this.type = type 
}; 
Animal.prototype.sayHello = function() { 
    return 'Hi, I am a ' + this.type 
}; 
var goat = new Animal('Goat'); 

我的理解是goat會繼承/參考Animal的功能。

推測我可以複製上述與下列對象字面概念:

var Animal = { 
    type : '', 
    sayHello : function() { 
     return 'Hi, I am a ' + this.type 
    } 
} 
var goat = Object.create(Animal); 
goat.type = 'Goat'; 

是繼承來Animal丟在這裏,或Goat仍引用Animal的方法呢?

我想知道是否有任何問題使用Object.create()而不是new複製構造函數/類。是否有一個性能偏移或任何理由繼續使用new

任何意見,將不勝感激,我很高興地補充說,如果需要澄清的問題。

更新的對象創建

var Animal = { 
    sayHello : function() { 
     return 'Hi, I am a ' + this.type 
    } 
} 
var goat = Object.create(Animal, { 'type' : { value: 'goat' } }); 
+0

你真的想在所有的呼叫站點輸入'goat.type'(以及更多)嗎?另外如果你想改變它,重構將會更加困難。這只是可怕的。在之前有人說「創建一個工廠」,在這種情況下,你只是做了美化的構造函數+原型。 – Esailija

+0

@Esailija我添加了關於如何填充'type'的更新。我很想看看你會如何處理這個問題。 – mikedidthis

+0

這比我剛纔批評的更糟糕:D它仍然處於呼叫站點,對象外部,甚至更詳細 – Esailija

回答

6

...以處理有不同的屬性,但同樣的方法將使用構造多個對象的常用方法...

是,另一種常見的方式是(如你所見)Object.create

我的理解是goat會繼承/引用Animal的功能。

不完全。在new Animal表達式中,goat被指定爲由Animal.prototype引用的對象作爲其基礎原型。沒有直接連接到Animal,只是到Animal.prototype。 (Animal.prototype有參考回到通過其constructor財產Animal,在事情發展的正常過程,但如果有人分配一個新的對象來Animal.prototype該鏈接可以得到打破。)

是繼承來Animal丟在這裏,或者是Goat仍然參考Animal的方法?

在您的非構造例如,goat得到Animal作爲其基礎的原型,所以在goat沒有發現自己財物時,JavaScript引擎將着眼於Animal,看是否有它。在您的示例中,這意味着goat使用sayHelloAnimal,而不是type,因爲goat有它自己的type

大致相當於這個:

function Animal (type) { 
    this.type = type 
}; 
Animal.prototype.sayHello = function() { 
    return 'Hi, I am a ' + this.type 
}; 
var goat = new Animal('Goat'); 

...使用Object.create設置原型,而不是像這樣:

var animalPrototype = { 
    sayHello: function() { 
     return 'Hi, I am a ' + this.type 
    } 
}; 
function createAnimal(type) { 
    var rv = Object.create(animalPrototype); 
    rv.type = type; 
    return rv; 
}; 
var goat = createAnimal('Goat'); 

回覆您的評論:

會有什麼問題,包括animalPrototype裏面createAnimal然後打電話Object.create(this.animalPrototype)

如果你的意思是這樣的:

function createAnimal(type) { 
    var animalPrototype = {      // Issue #1 
     sayHello: function() { 
      return 'Hi, I am a ' + this.type 
     } 
    }; 
    var rv = Object.create(this.animalPrototype); // Issue #2 
    rv.type = type; 
    return rv; 
}; 
var goat = createAnimal('Goat'); 

...然後是,有兩個問題:

  1. 你會創建一個新animalPrototype每次調用createAnimal,這打破了目的,並且2. this在呼叫createAnimal內將成爲全局對象(寬鬆模式)或undefined(嚴格模式),因此this.animalPrototype可能不是您想要的表達式。

你可以這樣做:

function createAnimal(type) { 
    var rv = Object.create(createAnimal.proto); 
    rv.type = type; 
    return rv; 
}; 
createAnimal.proto = { 
    sayHello: function() { 
     return 'Hi, I am a ' + this.type 
    } 
}; 
var goat = createAnimal('Goat'); 

可能是人的混亂,當然,因爲這看起來很像一個構造函數。

+2

+1非常好和客觀的總結髮生了什麼事。 OP - 用一個詞__Yes__,使用Object.create'可以讓你在JavaScript中做原型繼承。它會創建一個新對象,其_prototype_是您指定的對象。 (我在'喜歡對象。創建大多數情況下'一邊) –

+2

@BenjaminGruenbaum:謝謝!我採取相當均衡的看法。如果我創造的東西感覺「優雅」,我使用構造函數(通過我的[Lineage腳本](http://code.google.com/p/lineagejs/))。但是我總是使用'Object.create',我只需要一個與另一個特定對象基本相同但稍有不同的對象。我有一個項目,我們可以做很多事情,雖然它可以通過構造函數完成,但它會非常笨重。我發現他們都是非常有用的工具。我喜歡JavaScript的靈活性。 –

+0

@ T.J.Crowder非常感謝你的回答,它解決了我的幾個問題。我更新了我的問題刪除偏好,所以你可能需要更新開放的答案。再次謝謝你! – mikedidthis