…每个对象在同一个数组中也有对其他对象的引用?

当我第一次想到这个问题的时候,我就想到了

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中是否有可重用的方法来做到这一点?


当前回答

在2022年,我们可以使用structuredClone进行深度复制。

structuredClone(数组)

欲了解更多详情,请点击这里

其他回答

正如Daniel Lew提到的,循环图有一些问题。如果我有这个问题,我要么向有问题的对象添加特殊的clone()方法,要么记住我已经复制了哪些对象。

我会用一个变量copyCount来做,它在你每次复制代码时增加1。copyCount小于当前复制进程的对象将被复制。如果不是,则应该引用已经存在的副本。这就需要从原文链接到副本。

还有一个问题:内存。如果您从一个对象引用到另一个对象,那么浏览器很可能无法释放这些对象,因为它们总是从某个地方引用。您必须进行第二次传递,将所有复制引用设置为Null。(如果你这样做,你不必有一个copyCount,但一个布尔iscopy就足够了,因为你可以在第二步重置值。)

这个问题让我很沮丧。显然,当你发送一个泛型数组到$。扩展方法。因此,为了解决这个问题,我添加了一个小检查,它可以完美地与通用数组、jQuery数组和任何对象一起工作。

jQuery.extend({
    deepclone: function(objThing) {
        // return jQuery.extend(true, {}, objThing);
        /// Fix for arrays, without this, arrays passed in are returned as OBJECTS! WTF?!?!
        if ( jQuery.isArray(objThing) ) {
            return jQuery.makeArray( jQuery.deepclone($(objThing)) );
        }
        return jQuery.extend(true, {}, objThing);
    },
});

调用使用:

var arrNewArrayClone = jQuery.deepclone(arrOriginalArray);
// Or more simply/commonly
var arrNewArrayClone = $.deepclone(arrOriginalArray);

对于克隆对象,我只是建议ECMAScript 6 reduce():

const newArray = myArray.reduce((array, element) => array.push(Object.assign({}, element)), []);

但坦白说,我更喜欢恐龙的答案。我只是把这个版本放在这里作为另一个选择,但就我个人而言,我将使用map(),因为恐龙建议。

在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}]

更多细节:阅读这里

忘记eval()(它是JavaScript中最常被误用的特性,会使代码变慢)和slice(0)(只适用于简单的数据类型)

这对我来说是最好的解决方案:

Object.prototype.clone = function() {
  var myObj = (this instanceof Array) ? [] : {};
  for (i in this) {
    if (i != 'clone') {
        if (this[i] && typeof this[i] == "object") {
          myObj[i] = this[i].clone();
        }
        else
          myObj[i] = this[i];
    }
  }
  return myObj;
};