防止意外更改javascript原型

时间:2014-05-20 21:45:08

标签: javascript 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

如您所见,编辑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的引用不再引用原型。

但我对这种方法并不完全满意,因为当我添加更多内容时,我需要记住为每个对象属性执行此操作。不仅如此,我现在还有更胖的敌人对象,因为他们每个人都需要存储统计对象的副本。

我可以在这里使用更好的方法吗?

谢谢!

1 个答案:

答案 0 :(得分:2)

  

这似乎实际上是在改变原型而不是实例。

不,它改变了原型所指的对象。但它有很多相同的东西。 : - )

  

我相信这是因为敌人1和敌人2都没有名为stats的本地属性,所以enemy1.stats解析为原型值,这意味着它的力量值会被改变。

没错,是的。 (术语是"拥有"属性,而不是"本地"属性,但您已完全正确。)

  

我可以在这里使用更好的方法吗?

我认为你所拥有的是一种好方法。如果您愿意,可以自动化它(循环遍历this上的属性,对于typeof "object" extend的任何属性,通过stats运行它们,但从根本上说是您将要修改与实例关联的对象的属性,这些对象需要在实例上,而不是原型。

FWIW,我可能根本没有在原型上{{1}},只是在构造函数中。