Angular.copy() 不是深度复制引用的数组
Angular.copy() not deep copying referenced arrays
在我的 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()
会创建传入的任何内容的深层副本,我不应该遇到此问题。显然这是不正确的,那么为什么呢?有没有办法对坐标数组进行真正深度复制,从而消除奇怪的参考配对?我现在通过在reverse()
之前添加额外的angular.copy(newCoords[i])
来设法绕过它。
正如评论中所暗示的那样,这与 angular 核心内部的变化有关。此更改在 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 版本一起使用。这是将第三个参数传递到副本中以禁用循环引用处理。请注意,这也适用于 v1.2.17 之前的所有版本,因为它们将简单地忽略第 3 个参数并执行其默认行为:
var stackSource = angular.extend([], {push:angular.noop});
var newCoords = angular.copy(polygon.coordinates, null, noopArray);
第三个参数是未记录的stackSource
。通过重写它的推送方法而不执行任何操作,循环引用检测被破坏。需要注意的两件重要事情是循环引用会出错(如 v1.2.16 及更低版本),由于性能变化,这在 v1.4.8 及更高版本中不起作用。在这些情况下,您必须编写自己的深拷贝函数。
- 在javascript/angular中创建播放列表(按值复制数组,但按引用设置嵌套对象)
- Javascript函数 - 通过引用复制,但这里发生了什么
- 复制不带属性的函数引用
- 引用被分配给哪些类型,而不是在Javascript中被复制
- 在Javascript中使用新的引用创建一个新对象 - 不要复制或克隆 -
- 具有嵌套数组的绝对无引用的数组复制
- Angular/Javascript:按值复制一个简单的数字而不引用
- Angular.copy() 不是深度复制引用的数组
- 对于 JavaScript 的继承,引用或复制父级的原型是否更好
- 如何通过引用将JavaScript对象复制到新变量NOT
- 我应该从bower_components复制文件吗?在那里引用它们
- 多次循环引用对象,将其属性复制到Javascript/Angularjs中的其他对象
- Object.创建数组和对象属性的复制引用
- 通过值或引用复制/传递js中的函数
- 当通过引用而不是按值复制 JavaScript 值时,是否有任何经验法则
- Javascript:如何正确复制引用
- 通过引用复制对象是否有实际用途
- 自动复制index.html中的引用到karma.conf.js中
- 复制DOM节点jQuery(非引用)
- 尝试在JavaScript中复制引用传递行为:如何适当地修改我的代码