假设我有Player对象:
var player = function(name) {
this.handlers = {};
}
player.prototype.on = function(event, callback) {
if (!this.handlers[event]) {
this.handlers[event] = [];
}
this.handlers[event].push(callback);
}
它很棒,我可以创建玩家,每个玩家都有自己的处理程序。现在假设我需要继承player
:
var testPlayer = function(name) {
this.name = name;
};
testPlayer.prototype = new player();
现在,当我创建testPlayer
时,每个人共享相同的handlers
属性:
var adam = new testPlayer('Adam');
adam.on('test', function(){});
var eve = new testPlayer('Eve');
// eve.handlers == {'test':<function>}
我在这里缺少什么?我理解,每个testPlayer
的原型都是我在描述子类时创建的new player
对象。但是,有没有办法让所有testPlayers拥有自己的处理程序集?
答案 0 :(得分:5)
对于那些习惯于经典继承的人来说,这看起来确实很奇怪,但这就是原型继承的工作方式。要为每个实例分配一个处理程序对象,需要在子构造函数上指定一个。这将使原型的属性具有相同的名称:
var testPlayer = function(name) {
this.name = name;
this.handlers = {};
};
testPlayer.prototype = new player();
另一种解决方案是使用on
方法按需创建此阴影属性:
player.prototype.on = function(event, callback) {
// Check for a handlers property on the instance
if(!this.hasOwnProperty('handlers') {
this.handlers = {};
}
if (!this.handlers[event]) {
this.handlers[event] = [];
}
this.handlers[event].push(callback);
}
有趣的事实
如果您要修改原型上对象(或数组)的属性,这只是一个问题。如果您尝试分配原型上存在的属性,则会自动创建本地阴影属性(您无法从实例分配给原型属性)。
答案 1 :(得分:1)
这里的问题是handlers
是在构造函数中添加的属性,所以当你这样做时
testPlayer.prototype = new player();
您要将全新player
对象的所有属性添加到testPlayer.prototype
,而包含 handlers
。
因此,每个handlers
对象中都有一个testPlayer
属性,当您向handlers
添加属性时,您将属性添加到原型中的对象 < / em>,而不是testPlayer
对象。
简而言之,在调用on
方法时,您要向testPlayer.prototype.handlers
添加属性,而不是adam.handlers
或eve.handlers
。
为安全起见,请定义:
var testPlayer = function(name) {
this.name = name;
this.handlers = {};
};