…每个对象在同一个数组中也有对其他对象的引用?
当我第一次想到这个问题的时候,我就想到了
var clonedNodesArray = nodesArray.clone()
并搜索如何在JavaScript中克隆对象的信息。我确实在Stack Overflow上找到了一个问题(同样由@JohnResig回答),他指出用jQuery你可以做到
var clonedNodesArray = jQuery.extend({}, nodesArray);
克隆对象。虽然我尝试了这个,但这只复制了数组中对象的引用。如果我
nodesArray[0].value = "red"
clonedNodesArray[0].value = "green"
nodesArray[0]和clonedNodesArray[0]的值将显示为“绿色”。然后我尝试了
var clonedNodesArray = jQuery.extend(true, {}, nodesArray);
它深度复制了一个对象,但我分别从Firebug和Opera Dragonfly得到了“太多递归”和“控制堆栈溢出”的消息。
你会怎么做?这是不应该做的事情吗?在JavaScript中是否有可重用的方法来做到这一点?
在JavaScript中,数组和对象复制会改变原始值,因此深度复制是解决这个问题的解决方案。
深度复制实际上意味着创建一个新数组并复制值,因为无论它发生什么都不会影响原始数组。
JSON。解析和JSON。Stringify是深度复制的最佳和简单的方法。JSON.stringify()方法将JavaScript值转换为JSON字符串。JSON.parse()方法解析JSON字符串,构造由字符串描述的JavaScript值或对象。
深克隆
let a = [{ x:{z:1} , y: 2}];
let b = JSON.parse(JSON.stringify(a));
b[0].x.z=0
console.log(JSON.stringify(a)); //[{"x":{"z":1},"y":2}]
console.log(JSON.stringify(b)); // [{"x":{"z":0},"y":2}]
更多细节:阅读这里
浅拷贝的问题是所有对象都没有被克隆。虽然对每个对象的引用在每个数组中都是唯一的,但一旦最终获取到它,您将处理与以前相同的对象。你克隆它的方式没有问题…使用Array.slice()也会得到相同的结果。
深层复制出现问题的原因是您最终得到了循环对象引用。深度会尽可能地深,如果你有一个圈,它会无限延伸,直到浏览器昏厥。
如果数据结构不能表示为有向无环图,那么我不确定您是否能够找到用于深度克隆的通用方法。循环图提供了许多棘手的极端情况,由于这不是一个常见的操作,我怀疑是否有人编写了一个完整的解决方案(如果有可能的话——可能没有!)但是我现在没有时间来写一个严格的证明)。我在这个页面上找到了一些关于这个问题的很好的评论。
如果你需要一个带有循环引用的对象数组的深层副本,我相信你将不得不编写自己的方法来处理你的专用数据结构,这样它就是一个多通道克隆:
在第一轮中,克隆数组中不引用其他对象的所有对象。记录每个物体的起源。
在第二轮,把这些物体连在一起。