繁体   English   中英

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

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

使用 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 .slice(0)将有效地克隆具有原始类型元素的数组。 但是,在您的示例tags数组中包含匿名对象。 因此,对克隆数组中这些对象的任何更改都会反映在tags数组中。

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

这是另一个解决类似情况的线程

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

const clonedArray = [...oldArray];

MDN

在一行中执行此操作的最简单和乐观的方法是使用 Underscore/Lodash

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

您只需要使用 '...' 符号。

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

当你有一个数组说 x 时,[...x] 创建一个包含所有 x 值的新数组。 请小心,因为此符号在对象上的工作方式略有不同。 它将对象拆分为所有的键值对。 因此,如果要将对象的所有键值对传递给函数,则只需传递 function({...obj})

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

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

因此,每当我更改 $scope.MyData 时,也会更改 $scope.MyDataOriginal。 我找到了一个解决方案,angular.copy right 代码如下

 $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.parse 在 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, ...)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM