用javascript将一个对象数组复制到另一个数组中(深度复制)

Copying an array of objects into another array in javascript (Deep Copy)

本文关键字:数组 复制 深度 另一个 一个对象 javascript      更新时间:2023-10-13

使用slice(0)和concat()在javascript中将一个对象数组复制到另一个数组中是无效的。

我尝试了以下方法来测试我是否使用此方法获得深度复制的预期行为。但是,在我对复制的数组进行更改后,原始数组也会被修改。

var tags = [];
for(var i=0; i<3; i++) {
    tags.push({
        sortOrder: i,
        type: 'miss'
    })
}
for(var tag in tags) { 
    if(tags[tag].sortOrder == 1) {
        tags[tag].type = 'done'
    }
}
console.dir(tags)
var copy = tags.slice(0)
console.dir(copy)
copy[0].type = 'test'
console.dir(tags)
var another = tags.concat()
another[0].type = 'miss'
console.dir(tags)

如何将一个数组深度复制到另一个数组中,以便在复制数组中进行更改时不会修改原始数组。

尝试

var copy = JSON.parse(JSON.stringify(tags));

尝试以下

// Deep copy
var newArray = jQuery.extend(true, [], oldArray);

有关更多详细信息,请查看以下问题:在JavaScript中深度克隆对象的最有效方法是什么?

如前所述此处.slice(0)将有效地克隆具有基元类型元素的数组。但是,在您的示例中,tags数组包含匿名对象。因此,对克隆数组中这些对象的任何更改都会反映在tags数组中。

@dangh在上面的回复取消了这些元素对象并创建了新的对象。

这是另一个线程处理类似情况

用ES6克隆对象数组的一个好方法是使用spread语法:

const clonedArray = [...oldArray];

MDN

在一行中实现这一点最简单、最乐观的方法是使用Undercore/Lodash

设a=.map(b,_.clone)

您只需要使用"…"符号

// THE FOLLOWING LINE COPIES all elements of 'tags' INTO 'copy'
var copy = [...tags]

当你有一个数组,比如x时,[…x]会创建一个包含所有x值的新数组。请小心,因为这个符号在对象上的作用略有不同。它将对象拆分为所有的键值对。因此,如果你想把一个对象的所有键值对传递到一个函数中,你只需要传递函数({…obj})

同样的问题也发生在我身上。我有来自服务的数据,并保存到另一个变量中。当我更新我的数组时,复制的数组也会更新。旧代码如下

//$scope.MyData get from service
$scope.MyDataOriginal = $scope.MyData;

因此,当我更改$scope.MyData时,也会更改$scope.MyDataOriginal。我找到了一个解决方案,angular.复制正确的代码如下

$scope.MyDataOriginal = angular.copy($scope.MyData);

我知道这是一篇有点老的帖子,但我很幸运找到了一种不错的方法来深度复制数组,甚至是那些包含数组的数组和对象,甚至是包含数组的对象都被复制。。。我只能看到这段代码的一个问题是,如果你没有足够的内存,我可以看到它被非常大的数组和对象阻塞。。。但在大多数情况下,它应该起作用。我在这里发布这篇文章的原因是,它完成了OP请求,即按值而不是按引用复制对象数组。。。所以现在有了代码(检查来自so,这是我自己写的主要复制功能,而不是其他人以前可能没有写过,我只是不知道)::

var isArray = function(a){return (!!a) && (a.constructor===Array);}
var isObject = function(a){return (!!a) && (a.constructor===Object);}
Array.prototype.copy = function(){
    var newvals=[],
        self=this;
    for(var i = 0;i < self.length;i++){
        var e=self[i];
        if(isObject(e)){
            var tmp={},
                oKeys=Object.keys(e);
            for(var x = 0;x < oKeys.length;x++){
                var oks=oKeys[x];
                if(isArray(e[oks])){
                    tmp[oks]=e[oks].copy();
                } else { 
                    tmp[oks]=e[oks];
                }
            }
            newvals.push(tmp);
        } else {
            if(isArray(e)){
                newvals.push(e.copy());
            } else {
                newvals.push(e);
            }
        }
    }
    return newvals;
}

当调用对象或数组时,此函数(Array.prototype.copy)使用递归自行调用,并根据需要返回值。该过程速度相当快,并且完全按照您的意愿进行,它按值对数组进行深度复制。。。在chrome和IE11中进行了测试,它可以在这两种浏览器中工作。

用JSON在JavaScript中深度复制数组的方法。解析:

let orginalArray=
[
 {firstName:"Choton", lastName:"Mohammad", age:26},
 {firstName:"Mohammad", lastName:"Ishaque", age:26}
];
let copyArray = JSON.parse(JSON.stringify(orginalArray));
copyArray[0].age=27;
console.log("copyArray",copyArray);
console.log("orginalArray",orginalArray);

为此,我使用新的ECMAScript 6 Object.assign方法:

let oldObject = [1,3,5,"test"];
let newObject = Object.assign({}, oldObject)

该方法的第一个自变量是要更新的数组,我们传递一个空对象是因为我们想要一个全新的对象

还可以添加其他要复制的对象:

let newObject = Object.assign({}, oldObject, o2, o3, ...)