2014-11-24 100 views
4

在我的Angular应用程序中,我有一个引用多边形坐标的数组。例如:Angular.copy()不深拷贝引用数组

[[-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()创建任何传入的深层副本,我不应该遇到此问题。显然这是不正确的,那为什么?有没有办法去做一个真正的坐标数组的深层副本,消除了奇怪的参考配对?目前我已经设法解决了这个问题,在reverse()之前增加了一个angular.copy(newCoords[i])

+0

你能重现这个问题吗?对我而言,我正在为我使用同样的参考文献,是这样的吗? http://jsfiddle.net/rahpuser/2ngtw4bw/2/ – rahpuser 2014-11-24 15:05:37

+0

它在我的应用程序的角度版本中必须是angular.copy()的bug。如果你看这里(http://jsfiddle.net/2ngtw4bw/4/),按预期输出'false true false'。当我将该代码*完全*复制到我的应用程序中时,它会输出'false true true'。 – 2014-11-24 16:45:46

+0

实际上,它似乎可能是Angular 1.2.1(jsfiddle)和Angular 1.2.19(我的应用程序)之间的一个bug修复*。这取决于您的深层副本的定义是否包括在新对象中维护相对引用。 angular.copy文件应该可以使这个更清晰。 – 2014-11-24 17:01:48

回答

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(甚至全部回v0.9.0方式),因为它们的默认行为是为每个参考创建两个不同的克隆。


对于其他人来说,可能需要做一个深层副本,但不知道确切位置,其中重复引用(甚至可能是子对象),还有另外一种方法,将与角版本一起使用前到v1.4.8。这是将第三个参数传递给副本以禁用循环引用处理。请注意,这将会给v1.2.17以及之前所有版本,因为他们会简单地忽略第三个参数,做他们的默认行为:

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

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