2013-08-31 42 views
5

我有一個Java背景,最近我一直在嘗試JavaScript的繼承。我開始寫一些對象,在閱讀了一些例子後,我發現了最適合我的代碼風格。爲什麼在擴展對象時使用Object.create作爲原型?

以下是我有:

var Class = function() {}; 
Class.extend = function(p_constructor) { 
    var Superclass = this; 
    // the following line confuses me 
    p_constructor.prototype = Object.create(Superclass.prototype); 
    p_constructor.prototype.constructor = p_constructor; 
    p_constructor.extend = Superclass.extend; 
    return p_constructor; 
}; 

所以現在當我想定義延伸類的對象我只需要輸入:

var Person = Class.extend(function(p_firstName, p_lastName) { 
    this.firstName = p_firstName; 
    this.lastName = p_lastName; 
}); 

及以下爲真:

var p = new Person('john', 'smith'); 
p instanceof Person; // true 
p instanceof Class; // true 

我只是很難理解什麼是ef在Class.extend功能如下行之間fective區別:

/* 1) */ p_constructor.prototype = new Superclass(); 
/* 2) */ p_constructor.prototype = Superclass.prototype; 
/* 3) */ p_constructor.prototype = Object.create(Superclass.prototype); 
/* 4) */ p_constructor.prototype = Object.create(Superclass); 

我也知道使用一號線是不是很明智的,如果一些超級構造函數拋出錯誤,但什麼也正是線2,3和4之間的區別?

回答

6

要回答我的問題:

/* 1) */ p_constructor.prototype = new Superclass(); 

就像我說的,這不是很明智的使用,因爲它實際上創造了整個超類對象。原型繼承的要點是共享原型對象,因此可以避免多餘的函數(有時是對象)定義。

/* 2) */ p_constructor.prototype = Superclass.prototype; 

如果你能確定構造函數的原型永遠不會被第三方修改,這將是確定的。假設某個使用你的類的人想要爲其原型添加額外的功能。改變p_constructor的原型會直接影響超類的原型,並可能在超類的行爲中引入錯誤。所以下一行代碼來代替:

/* 3) */ p_constructor.prototype = Object.create(Superclass.prototype); 

這將創建一個新的對象(實例),其原型(實際上是__proto__變量)設置爲超類的原型。現在對p_constructor.prototype的任何更改都不會更改超類的行爲。

/* 4) */ p_constructor.prototype = Object.create(Superclass); 

上面一行有效,但沒有意義,因爲它只將原型設置爲超類的構造函數。

此外,以下行混淆了我還有:

p_constructor.prototype.constructor = p_constructor; 

這使得在p_constructor的行爲沒有什麼區別,它不僅使參考實例化對象提供的構造函數。一個絕招就是超添加到原型,以及:

p_constructor.prototype.superclass = Superclass; 

,然後將下面的代碼段將工作:

function Constructor(p_params) { 
    // call constructor of the superclass 
    this.superclass(p_params); 
} 
+0

酷,你在這裏回答你的問題。在你最後一塊代碼中,當你這樣調用超類的構造函數時,請考慮它的上下文;我認爲你想要做的是'this.superclass.apply(this,arguments);' - 那麼,如果super的構造函數變爲'this.sumthin = ...',那麼該值將附加到子類的實例。 – dalgard

+0

無論如何,來自超類的值將被附加到子類的當前實例,因爲它是從'this'調用的,所以它的上下文實際上是子類的新實例。 – jeremija

+0

哦,你說得對。我想我更經常地看到這種模式:'subclass.prototype.super = superclass.prototype'(可能加上'subclass.super = superclass')。也許你有興趣查看[我的解決方案](https://gist.github.com/dalgard/9169923)這些東西(請參閱評論中的示例)。 – dalgard

相關問題