【问题标题】:Changing an Object's attributes also Affects Another Object改变一个对象的属性也会影响另一个对象
【发布时间】:2012-12-13 08:36:18
【问题描述】:

问题:当我改变一个多边形poly2points时,它也改变了另一个多边形polypoints!!

为什么改变一个也会改变另一个,我们如何将它们解耦

console.log(poly.getPoints()[1].x);  // 100

// Make a change to `poly2`
poly2.setPoints(poly.getPoints());
poly2.getPoints()[1].x=200

console.log(poly.getPoints()[1].x);  // 200 (both poly and poly2 are affected!)

jsfiddle: http://jsfiddle.net/8hFyv/

【问题讨论】:

  • 请在帖子中包含代码。

标签: javascript jquery html canvas kineticjs


【解决方案1】:
poly2.setPoints(poly.getPoints());

这是你的问题。 points 数组是同一个对象。

由于您的数组中有数组,slice(0) 技巧将不起作用,您需要深拷贝。

幸运的是,您使用的是 jQuery,它有一种方法可以做到这一点。

将上面的行替换为:

poly2.setPoints($.extend(true, [], poly.getPoints()));

【讨论】:

  • 在某种程度上。我们宁愿说它返回一个对象引用,因为 JavaScript 没有指针作为可以操作的原始类型。但是所有对象都以这种方式运行。考虑一下:a = {}; b = a; a.x = 3; console.log(b.x) 将打印 3 - 因为 b = a 使 b 成为对 a 所引用的同一对象的引用。
【解决方案2】:

当您执行此操作时,您的 poly 和 poly2 对象正在引用相同的点数组:

poly2.setPoints(poly.getPoints());

改成这样:

poly2.setPoints([0, 0, 100, 0, 100, 100, 0, 100]);

【讨论】:

  • 我需要通过将poly.setPoints() 传入一个与poly.getPoints() 返回的值完全相同的数组来设置poly2。听起来可能很简单,但我该怎么做呢?
  • 调用 poly.getPoints().slice() 以获得数组的副本(而不是对数组的引用的副本)
  • slice 不起作用,因为它太浅了 - getPoints() 返回一个对象数组,而不是原始数组。
【解决方案3】:

要克隆点,而不是在多边形之间共享它们,您需要自己为每个点创建新对象。

您可以使用map

poly2.setPoints(poly.getPoints().map(function (p) {
    return { x: p.x, y: p.y };
}));

或者,jQuery.map:

poly2.setPoints($.map(poly.getPoints(), function (p) {
    return { x: p.x, y: p.y };
}));

【讨论】:

    【解决方案4】:

    其他答案在评估问题时是正确的,但还有另一种方法可以解决它:在设置点数组时“克隆”它。换句话说:

    poly2.setPoints(poly.getPoints().slice());
    

    如果出于某种原因getPoints() 返回的不是数组,您将需要一种不同的克隆方法(例如 axel.michel 建议的方法),但我认为它应该适合您。

    【讨论】:

    • console.log(poly.getPoints()) 在 Chrome 开发工具中告诉我它是一个数组,返回 [0, 0, 100, 0, 100, 100, 0, 100]!所以 Chrome 错了?
    • 它是一个数组。正如我在其他地方指出的那样,.slice() 不起作用,因为它是一个两层深的数组 - .slice() 只会执行浅拷贝,但仍会共享保存单个坐标的迷你对象 { x: ..., y: ... }。跨度>
    • @Nyxynyx:这就是我得到的:[{"x":0,"y":0},{"x":100,"y":0},{"x":100,"y":100},{"x":0,"y":100}]。正如你所说,我没有得到平面阵列。你能再检查一下吗?
    • 是的,我得到的和你一样。我猜数组中的对象的行为方式与您在答案评论中解释的方式相同。我需要解决一些问题,出于某种奇怪的原因,我在执行 javascript/jquery/backbone/nodejs 很长一段时间后没有遇到这个问题......
    • 首先,快速术语点:这是一个“平面”数组,因为它不包含任何子数组。但是,它确实包含对象,并且在您克隆阵列时不会克隆这些对象,因此您必须手动克隆它们。其他回答者提供了其他替代方案,jQuery 和 Underscore 等主要库也有可以使用的克隆方法。
    【解决方案5】:

    问题是,poly.getPoints 是一组动力学指针对象,要摆脱它,请尝试以下操作:

    poly2.setPoints(JSON.parse(JSON.stringify(poly.getPoints())));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多