Angular.copy()不会深度复制引用的数组

时间:2014-11-24 14:32:54

标签: javascript angularjs reference deep-copy shallow-copy

在我的Angular应用程序中,我有一个引用多边形坐标的数组。例如:

[[-1,0], [0,1], [1,0], [0,-1], [-1,0]]

这里重要的一点是重复第一个和最后一个点,并实际引用相同的 2长度数组。这是我使用的插件的结果。但是,有时会以这样的方式创建数组:第一个和最后一个点虽然具有相同的值,但它们的引用不同。

在我的Angular应用程序中的某个点,我需要创建一个与原始坐标相同的新多边形,只需要翻转。我的第一次尝试是这样的:

var newCoords = angular.copy(polygon.coordinates);
for (var i = 0; i < newCoords.length; i++) {
  newCoords[i].reverse();
}

然而,在第一个和最后一个坐标具有相同参考的情况下,我最终得到的一个点被反转两次。

我的理解是angular.copy()创建了传入的任何内容的深层副本,我不应该遇到这个问题。显然这是不正确的,为什么呢?有没有办法做一个真正的坐标数组的深层副本,消除奇怪的参考配对?我现在通过在angular.copy(newCoords[i])之前添加额外的reverse()来设法绕过它。

1 个答案:

答案 0 :(得分:1)

正如评论中所暗示的那样,这与角度核心内部的变化有关。此更改已在Angular v1.2.17中发布。错误修复列为:

  

angular.copy:支持要复制的值中的循环引用   (5c997209#7618

但是,除了循环引用外,还会处理双引用。要故意不处理双引用,您有几个选项。就像你在帖子中提到的那样,在预制复制后,重新复制第一个索引。不是特别直观,但在任何情况下它都可以正常工作:

var newCoords = angular.copy(polygon.coordinates);
// Ensure unique reference for the first element
newCoords[0] = angular.copy(newCoords[0]);

另一种选择是在v1.2.17之前使用任何Angular版本(甚至一直回到v0.9.0),因为它们的默认行为是为每个引用创建两个不同的克隆。

对于可能需要进行深层复制,但不知道哪些重复引用的确切位置(甚至可能在子对象中)的其他人,还有另一种方法可用于v1.4.8之前的Angular版本。这是将第三个参数传递给copy以禁用循环引用处理。请注意,这也适用于v1.2.17之前的所有版本,因为它们将忽略第3个参数并执行其默认行为:

var stackSource = angular.extend([], {push:angular.noop});
var newCoords = angular.copy(polygon.coordinates, null, noopArray);

第三个参数是 无证件 stackSource。通过重写它的推送方法什么也不做,循环参考检测被打破了。需要注意的两个重要事项是循环引用会出错(如v1.2.16和down),由于性能变化,这在v1.4.8及更高版本中不起作用。在这些情况下,您必须编写自己的深层复制功能。