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

在javascript中将对象数组复制到另一个数组中(深度复制),javascript,arrays,node.js,google-chrome,deep-copy,Javascript,Arrays,Node.js,Google Chrome,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) {

使用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标记=[];
对于(var i=0;iTry

试试下面的方法

// Deep copy
var newArray = jQuery.extend(true, [], oldArray);
有关更多详细信息,请查看此问题。

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

@上面dangh的回答取消了对这些元素对象的保护并创建了新的元素对象


解决类似情况

为此,我使用了新的ECMAScript 6方法:

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

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

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

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

设a=u0.map(b,0.clone)


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

/$scope.MyData从服务获取

$scope.MyDataOriginal=$scope.MyData;
使用ES6克隆对象数组的好方法是使用扩展语法:

const clonedArray = [...oldArray];

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

var isArray=function(a){return(!!a)&&(a.constructor==Array);}
var isObject=function(a){return(!!a)&&(a.constructor==Object);}
Array.prototype.copy=函数(){
var newvals=[],
self=这个;
for(var i=0;i

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

您只需要使用“…”符号

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

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

我不知道你想做什么,但我建议将你的第二个for循环改为a
for of
loop
for of(var-tag of-tags){if(tag.sortOrder==1){tag.type=='done'}}}
根据你的环境,你可以尝试Object.create吗?@zlatko你能给出一个sameOh的例子,var-newObject=Object.create(oldObject)应该给你一个旧对象的基于proto的、取消引用的克隆。对数组不确定,你可以试试。评论的环境部分是,我不知道你是否在V8或其他JS引擎上,我认为它不是到处都支持的(但有polyfils)。实际上似乎是这样的:经过一年半的时间,仍然很有用!@Aerious嗯,这很有效,因为您正在将数组/对象序列化为字符串。当您解析该字符串时,将实例化全新的对象,就像您从某些api收到有效负载一样。但是引用不会保留,因此如果您有指向其他元素,这将是危险的。@SavaB.Agreed:)请记住,如果数组中的任何对象(标记)是循环结构,这将不起作用,这意味着它间接引用自身。这种情况将以“TypeError:将循环结构转换为JSON”结束错误。这不起作用,因为结果是一个对象,而不是一个数组。即使使用object.assign,您也有同样的问题,Javascript中现在存在的每个方法都可以与原语一起工作,如果您的对象的键与另一个对象的值相同,则引用将是keptt这是浅拷贝他需要深拷贝,而不是浅拷贝。th不会产生深度复制,新数组中的对象仍将引用旧数组中的对象,好的。抱歉
const clonedArray = [...oldArray];
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;
}
// THE FOLLOWING LINE COPIES all elements of 'tags' INTO 'copy'
var copy = [...tags]