[英]JavaScript prototypal inheritance workaround
這是一個例子:
var Box = function() {
this.id = generateUniqueId();
};
Box.prototype = {
add:function(parent) {
parent.appendChild(this.elm);
}
};
var NewBox = function() {
this.newThing = true;
};
NewBox.prototype = new Box();
NewBox.prototype.remove = function() {
this.elm.parentNode.removeChild(this.elm);
};
var a = new NewBox();
var b = new NewBox();
alert(a.id); // alerts 0
alert(b.id); // also alerts 0! :@
我希望a和b(基本上每次創建NewBox
)都有自己的id
。 我了解到NewBox
使用的是原型繼承,因此是從Box
生成的id
的單個實例繼承的,但是我希望這樣做,以便每個NewBox
都有自己的id
而不必在NewBox
構造函數中明確NewBox
。
也許這是不可能的,或者我做錯了什么,所以請幫助!
非常感謝!
在您的示例中,僅當您設置NewBox.prototype
對象時,才執行Box
構造函數。
您可以通過使用Function.prototype.apply
方法在NewBox
調用Box
構造函數來解決此問題,以設置this
值並轉發所有參數值,例如:
//..
var NewBox = function() {
Box.apply(this, arguments);
this.newThing = true;
};
//..
var a = new NewBox();
var b = new NewBox();
// assuming your `generateUniqueId` function
// increments a number
alert(a.id); // will alert 1
alert(b.id); // will alert 2
現在,每次調用NewBox
構造函數創建一個新的對象實例( new NewBox();
)時,它將調用Box
函數在其上應用其所有邏輯。 這將幫助您避免一遍又一遍地重復父構造函數的邏輯。
使用apply
調用“父”構造函數, this
值設置為由NewBox
構造函數創建的對象實例,然后將提供給該函數的所有參數傳遞給該實例。
當您通過NewBox.prototype = new Box();
表示繼承關系時,您的示例還顯示了一個常見問題NewBox.prototype = new Box();
Box
構造函數被調用且具有副作用,此新對象將被初始化,並且您的generateUniqueId
函數將首次執行,如果要避免這種情況,您需要使用temp構造函數,只是為了創建一個新的繼承自Box.prototype
對象,或出於相同目的使用新的ECMAScript 5 Object.create
方法,例如:
function inherit(o) {
function Tmp() {}
Tmp.prototype = o;
return new Tmp();
}
//.....
NewBox.prototype = inherit(Box.prototype);
要么:
NewBox.prototype = Object.create(Box.prototype);
這樣,您無需第一次運行Box
構造函數即可表示相同的繼承層次結構,從而避免了可能引起的任何副作用。
最后但並非最不重要的一點是,始終建議您每次替換函數的prototype屬性時,都要還原此新原型對象的constructor
屬性,否則它將指向錯誤的函數。
在您的示例中,由於您將NewBox.prototype
替換為Box
的新實例,因此NewBox.prototype.constructor
屬性將指向Box
,(您的實例受到影響,例如a.constructor === Box; // true
)如您NewBox
,將其設置為NewBox
,我們需要將其重新設置,例如:
NewBox.prototype = someObject; // as any of the examples above
NewBox.prototype.constructor = NewBox;
您可以將這些細節抽象為一個函數,就像我在上面的inherit
函數中所做的那樣:
function inherits(child, parent) {
var obj, Tmp = function () {};
Tmp.prototype = parent.prototype;
obj = new Tmp();
child.prototype = obj;
child.prototype.constructor = child;
}
//...
// instead of setting the `NewBox.prototype` manually
inherits(NewBox, Box); // "NewBox inherits from Box"
//...
也許這是不可能的,或者我做錯了什么,所以請幫助!
您做錯了。
如果需要特定於實例的值,請在構造函數而不是原型中初始化它們。
馬特·鮑爾(Matt Ball)有正確的想法。 而是嘗試:
var Box = (function(){
var numberOfBoxes = 0;
function() {
this.id = numberOfBoxes++;
}
})();
或者,如果您希望所有(不同的)類具有唯一的ID:
var generateUniqueID = (function(){
var runningCount = 0;
return function (){
return runningCount++;
}
})();
var Box = function() {
this.id = generateUniqueId();
};
var NewBox = function() {
this.id = generateUniqueId();
this.newThing = true;
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.