簡體   English   中英

JavaScript原型繼承解決方法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM