javascript - 防止意外更改 JavaScript 原型(prototype)

标签 javascript prototype

我在寻找防止意外更改对象原型(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/

相关文章:

javascript - 在谷歌浏览器中禁用位置栏

javascript - 如何使用 javascript 并根据提供的输入获取 JSON 数据?

javascript - PrototypeJs 中的 $$ 和 $

javascript - 重新分配内置类型的原型(prototype)

javascript - 如何添加像 num.tf(n) 这样的方法作为 num.toFixed(n) 的别名

javascript - 如何使用 Webpack 构建 React 应用程序并导入 Assets 文件夹?

javascript - 在 AG Grid 列标题中呈现 HTML (Community v20.0.0 +)

javascript - jQuery - 滚动到具有动态类的元素

javascript - 函数的子函数作为原型(prototype)

Javascript - 原型(prototype)设计的值(value)是什么?