繁体   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