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