我遇到了一些麻烦,找到了防止对象原型意外更改的方法。以下示例有助于澄清我的问题:
var Enemy, enemy1, enemy2;
Enemy = (function() {
function Enemy() {}
Enemy.prototype.speed = 10;
Enemy.prototype.stats = {
strength: 15
dexterity: 12
};
return Enemy;
})();
enemy1 = new Enemy();
enemy2 = new Enemy();
enemy1.speed = 20;
enemy1.stats.strength = 25;
console.log("enemy1 speed: " + enemy1.speed);
console.log("enemy2 speed: " + enemy2.speed);
console.log("enemy1 str: " + enemy1.stats.strength);
console.log("enemy2 str: " + enemy2.stats.strength);
结果:
console: enemy1 speed: 20
console: enemy2 speed: 10
console: enemy1 str: 25
console: enemy2 str: 25
如您所见,编辑enemy1上的原始属性(例如speed
)不会影响敌人2。但是当对象属性中的属性在enemy1上更改时(例如stats.strength
),这似乎实际上是在改变原型而不是实例。
我相信这是因为enemy1和enemy2都没有名为stats
的本地属性,因此enemy1.stats
会解析为原型值,这意味着strength
的值会被更改。
通过将Enemy的构造函数更改为:
,我想出了解决此问题的方法function Enemy() {
//using jQuery to deep copy the stats property in the prototype
this.stats = $.extend(this, Enemy.prototype.stats);
}
这会初始化stats的本地属性,这意味着对enemy1.stats
的引用不再引用原型。
但我对这种方法并不完全满意,因为当我添加更多内容时,我需要记住为每个对象属性执行此操作。不仅如此,我现在还有更胖的敌人对象,因为他们每个人都需要存储统计对象的副本。
我可以在这里使用更好的方法吗?
谢谢!
答案 0 :(得分:2)
这似乎实际上是在改变原型而不是实例。
不,它改变了原型所指的对象。但它有很多相同的东西。 : - )
我相信这是因为敌人1和敌人2都没有名为stats的本地属性,所以enemy1.stats解析为原型值,这意味着它的力量值会被改变。
没错,是的。 (术语是"拥有"属性,而不是"本地"属性,但您已完全正确。)
我可以在这里使用更好的方法吗?
我认为你所拥有的是一种好方法。如果您愿意,可以自动化它(循环遍历this
上的属性,对于typeof
"object"
extend
的任何属性,通过stats
运行它们,但从根本上说是您将要修改与实例关联的对象的属性,这些对象需要在实例上,而不是原型。
FWIW,我可能根本没有在原型上{{1}},只是在构造函数中。