复制对象数组 [英] copy array of objects

查看:25
本文介绍了复制对象数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在创建对象数组的副本时遇到问题.我无法获得指向新的独立数组的新引用.

I'm having issues creating a copy of an object array. I can't get the new reference to point to a new independent array.

function OBJ1(name, tags) {
    this.myname = name;
    this.mytags = tags;
    this.myvalue = 0;
}

function OBJ2(arg1) {
    this.arg1 = arg1;
    this.myarray = [];
}

var OBJ1_array = [];
var result_array2 = null;
var result;
OBJ1_array = createarray1();
for (i = 0; i < 2; i++) {
    result = createarray2();
}

function createarray1() {
    var myarray = [];
    myarray.push(new OBJ1("NAME", [1, 2, 3]));
    myarray.push(new OBJ1("others", [1, 2, 3]));
    myarray.push(new OBJ1("total", [1, 2, 3]));
    return myarray;
}

function createarray2() {
    var newarray = $.extend(true, [], OBJ1_array); // newarray should refer to a new array, not the same one as OBJ1_array
    OBJ1_array[0].myname = "CHANGED";
    console.log("categories", JSON.parse(JSON.stringify(OBJ1_array)));
    console.log("newarray", JSON.parse(JSON.stringify(newarray)));
}

输出:

testscript.js:45 categories (3) [{…}, {…}, {…}]0: {myname: "CHANGED", mytags: Array(3), myvalue: 0}1: {myname: "others", mytags: Array(3), myvalue: 0}2: {myname: "total", mytags: Array(3), myvalue: 0}length: 3__proto__: Array(0)
testscript.js:46 newArray (3) [{…}, {…}, {…}]0: {myname: "CHANGED", mytags: Array(3), myvalue: 0}1: {myname: "others", mytags: Array(3), myvalue: 0}2: {myname: "total", mytags: Array(3), myvalue: 0}length: 3__proto__: Array(0)

我希望OBJ1_array[0].myname="CHANGED";对新创建的数组newArray没有影响. 我尝试过但不起作用的事情:

I expected OBJ1_array[0].myname="CHANGED"; to have no effect on the newly created array newArray. Things I've tried and didn't work:

var newArray = OBJ1_array.map(a => ({...a}));
var newarray=$.extend(true,[],OBJ1_array);

我该如何解决这个问题?

How can I solve this issue?

推荐答案

$.extend 文档指出以下内容:

The $.extend documentation says the following:

未定义的属性不会被复制.但是,将从对象的原型继承的属性复制过来. 通过new MyCustomObject(args)构造的对象或内置JavaScript类型(例如Date或RegExp)的属性不会重新构造,并会在结果对象或数组中显示为纯对象. >

Undefined properties are not copied. However, properties inherited from the object's prototype will be copied over. Properties that are an object constructed via new MyCustomObject(args), or built-in JavaScript types such as Date or RegExp, are not re-constructed and will appear as plain Objects in the resulting object or array.

这意味着其中具有所有普通对象的数组将被深度合并/复制.但是,用new关键字创建的对象将不会被重建.这使我们处于以下情况:

This means that the array with all plain object in it will be deeply merged/copied. However objects created with the new keyword will not be reconstructed. This leaves us with the following scenario:

数组副本工作得很好,但是由于数组元素是使用new关键字创建的,因此它们不会进一步合并.更改数组本身(按入,弹出等)时,您会看到该数组确实是一个副本.

The array copy works just fine, however since the elements in the array are created using the new keyword they are not further merged. When altering the array itself (pushing, popping, etc.) you can see that the array is indeed a copy.

这里的问题是,您访问数组中的元素之一并更改对象(使用new关键字创建).这两个数组仍指向同一对象,因此,从另一个持有相同对象引用的数组中读取时,您也会看到此更改.

The issue here is that you access one of the elements in the array and change the object (created with the new keyword). Both arrays still point to the same object, thus when reading from the other array which hold the same object reference you will also see this change.

要解决此问题,您还必须进行复制.根据您的用例,您可能可以使用 Object.create 在盲目使用它们之前,请先阅读文档.

To resolve this issue you have to also make a copy of each object in the array. Depending on your use-case you might be able to use Object.assign or Object.create have a look at the documentation before using them blindly.

我还创建了一个您遇到的问题的最小示例,以使您对问题有更好的了解.

I've also created a minimal example of the problem you face to give you some better understanding of the issue.

// setup
var array1, array2, array3, array4;
function Dummy(name) { this.name = name }


// test #1 - using plain objects
array1 = [{ name: 'Foo' }];
array2 = $.extend(true, [], array1);

array1[0].name = 'Bar';

console.log(array1[0].name, array2[0].name);


// test #2 - using the `new` keyword
array3 = [new Dummy('Foo')];
array4 = $.extend(true, [], array3);

array3[0].name = 'Bar';

console.log(array3[0].name, array4[0].name);

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

这篇关于复制对象数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆