我在寻找防止意外更改对象原型(prototype)的方法时遇到了一些麻烦。下面的示例应该有助于澄清我的问题:
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
如您所见,编辑敌人 1 的基本属性(例如 速度
)不会影响敌人 2。但是,当敌人1上的对象属性中的属性发生变化时(例如stats.strength),这似乎实际上是在改变原型(prototype)而不是实例。
我相信这是因为敌人1和敌人2都没有名为stats
的本地属性,因此enemy1.stats
解析为原型(prototype)值,这意味着它的值 >强度
被改变。
我想出了一种方法来解决这个问题,将 Enemy 的构造函数更改为:
function Enemy() {
//using jQuery to deep copy the stats property in the prototype
this.stats = $.extend(this, Enemy.prototype.stats);
}
这会初始化 stats 的本地属性,这意味着对 enemy1.stats
的引用不再引用原型(prototype)。
但我对这种方法并不完全满意,因为当我添加更多对象属性时,我需要记住为每个对象属性执行此操作。不仅如此,我现在还获得了更胖的 Enemy 对象,因为它们每个都需要存储 stats 对象的副本。
我可以在这里使用更好的方法吗?
谢谢!
最佳答案
this seems to actually be altering the prototype instead of the instance.
不,它正在改变原型(prototype)引用的对象。但事情大致相同。 :-)
I believe this is because neither enemy1 nor enemy2 have a local property called stats, so enemy1.stats resolves to the prototype value, meaning that its value for strength is altered.
没错,是的。 (术语是“自己的”属性(property),而不是“本地”属性(property),但你说得完全正确。)
Is there a better approach I can use here?
我认为你的方法很好。如果您愿意,您可以自动化它(循环遍历 this
上的属性,并且对于任何将 typeof
作为 "object"
的属性,运行它们通过extend
),但从根本上来说,如果您要修改与实例关联的对象的属性,这些对象需要位于实例上,而不是原型(prototype)上。
FWIW,我可能根本不会在原型(prototype)上有stats
,而只是在构造函数中。
关于javascript - 防止意外更改 JavaScript 原型(prototype),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23770511/