2013-02-23 37 views
7

我正在學習面向對象的Javascript的一些方面。我碰到這個片段Javascript繼承:設置原型時調用Object.create

var Person = function(firstName, lastName) 
{ 
    this.lastName = lastName; 
    this.firstName = firstName; 
}; 

Object.defineProperties(Person.prototype, { 
    sayHi: { 
    value: function() { 
     return "Hi my name is " + this.firstName; 
    } 
    }, 
    fullName: { 
    get: function() { 
     return this.firstName + " " + this.lastName; 
    } 
    } 
}); 

var Employee = function(firstName, lastName, position) { 
    Person.call(this, firstName, lastName); 
    this.position = position; 
}; 

Employee.prototype = Object.create(Person.prototype); 

var john = new Employee("John", "Doe", "Dev"); 

我的問題是:爲什麼這個片段中使用 的Object.create(Person.prototype的)?我們不應該簡單地重置原型:

Employee.prototype = Person.prototype; 
+2

一個偉大的【答案】(http://stackoverflow.com/questions/15040955/javascript-oop-and-prototypes-with-multiple-level-inheritance?answertab=active#從今天開始到此爲止。 – marekful 2013-02-23 20:16:31

+0

哇。感謝那。爲學習書籤! :-) – 2013-02-23 20:21:16

+0

[編號](http://stackoverflow.com/q/12500637/1048572) – Bergi 2013-02-23 22:44:16

回答

9

做Employee.prototype = Person.prototype就像是說「員工是人」而不是「員工是人」。對原型的任何更改都將反映在這兩個類中。

這裏是demonstration。顯然,我們不希望我們的員工因爲沒有職位而工作。

所以正確的方式來設置,但不的Object.create原型鏈是:

Employee.prototype = new Person; 

但這需要實例化對象,這是一個有點古怪 - 特別是如果你不希望人的構造函數叫做。無論您是否想要,所有員工實例都將繼承未定義的「firstName」和「lastName」屬性。

在這種情況下,沒有什麼大不了的 - Employee構造函數將在自身上設置這些屬性,這將取代從Person繼承的屬性。但考慮到this example。有人可能會認爲freeTime是Person的一個實例級屬性,它不會被複制,因爲它不在原型上。另外,我們從來沒有從Employee調用Person構造函數。不是如此 - freeTime 在Employee原型上設置的,因爲我們必須實例化一個對象。

因此,您可以通過Object.create進行最好和最乾淨的繼承。如果你想調用父類的構造函數,你可以從子類的構造函數中明確地這樣做。另一個好處是Object.create對defineProperties有第二個(可選)參數。所以你也可以這樣做:

Employee.prototype = Object.create(Person.prototype, { 
    work: { 
    value: function() { 
     return this.fullName+" is doing some "+this.position+" stuff"); 
    } 
    } 
}); 

當然,如果你必須支持傳統的瀏覽器,你不能使用Object.create。另一種方法是從庫中使用克隆/擴展,如下劃線或lodash。或者有這個小舞:

var subclass = function() { }; 
subclass.prototype = Person.prototype; 
Employee.prototype = new subclass; 
+0

爲什麼這是正確的方法?我的意思是,如果Person對象具有屬性/字段(firstName,lastName)呢?員工的原型應該可以訪問嗎?而且我還需要提供lastName&firstName,因爲構造函數需要它們。 – dragonfly 2013-02-23 21:15:29

+0

更新了演示。 – 2013-02-23 21:20:05

+0

我認爲這裏給出的例子是不好的。我*會*期待'freetime'被複制到子對象,因爲它是在父類的構造函數中設置的,並且您打算從子構造函數中調用該構造函數。 – Jez 2015-07-01 15:01:15

1

我的猜測是,目的是創建一個新的對象,而不是從Person引用。

//create a new object with its prototype assigned to Person.prototype 
Employee.prototype = Object.create(Person.prototype);