将JavaScript中的数组复制到另一个数组时:
var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d'); //Now, arr1 = ['a','b','c','d']
我意识到arr2指的是与arr1相同的数组,而不是一个新的独立数组。如何复制阵列以获得两个独立的阵列?
将JavaScript中的数组复制到另一个数组时:
var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d'); //Now, arr1 = ['a','b','c','d']
我意识到arr2指的是与arr1相同的数组,而不是一个新的独立数组。如何复制阵列以获得两个独立的阵列?
当前回答
在Javascript中,深度复制技术依赖于数组中的元素。让我们从这里开始。
三种类型的元素
元素可以是:文字值、文字结构或原型。
// Literal values (type1)
const booleanLiteral = true;
const numberLiteral = 1;
const stringLiteral = 'true';
// Literal structures (type2)
const arrayLiteral = [];
const objectLiteral = {};
// Prototypes (type3)
const booleanPrototype = new Bool(true);
const numberPrototype = new Number(1);
const stringPrototype = new String('true');
const arrayPrototype = new Array();
const objectPrototype = new Object(); // or `new function () {}
从这些元素中,我们可以创建三种类型的数组。
// 1) Array of literal-values (boolean, number, string)
const type1 = [ true, 1, "true" ];
// 2) Array of literal-structures (array, object)
const type2 = [ [], {} ];
// 3) Array of prototype-objects (function)
const type3 = [ function () {}, function () {} ];
深度复制技术取决于三种阵列类型
根据数组中元素的类型,我们可以使用各种技术进行深度复制。
深度复制技术
基准
https://www.measurethat.net/Benchmarks/Show/17502/0/deep-copy-comparison
文字值数组(类型1)[…myArray]、myArray.splice(0)、myArrax.slice()和myArray.concat()技术可用于深度复制仅具有文字值(布尔值、数字和字符串)的数组;其中slice()在Chrome中具有最高的性能,并且扩展。。。在Firefox中具有最高的性能。文本值(类型1)和文本结构(类型2)的数组JSON.parse(JSON.stringify(myArray))技术可用于深度复制文本值(布尔值、数字、字符串)和文本结构(数组、对象),但不能复制原型对象。所有数组(类型1、类型2、类型3)Lo-dash-cloneDeep(myArray)或jQuery-extend(true,[],myArray)技术可用于深度复制所有数组类型。其中Lodash cloneDeep()技术具有最高的性能。对于那些避免使用第三方库的用户,下面的自定义函数将深度复制所有数组类型,性能低于cloneDeep(),性能高于extend(true)。
function copy(aObject) {
// Prevent undefined objects
// if (!aObject) return aObject;
let bObject = Array.isArray(aObject) ? [] : {};
let value;
for (const key in aObject) {
// Prevent self-references to parent object
// if (Object.is(aObject[key], aObject)) continue;
value = aObject[key];
bObject[key] = (typeof value === "object") ? copy(value) : value;
}
return bObject;
}
所以要回答这个问题。。。
问题
var arr1 = ['a','b','c'];
var arr2 = arr1;
我意识到arr2指的是与arr1相同的数组,而不是一个新的独立数组。如何复制阵列以获得两个独立的阵列?
答复
因为arr1是一个文本值数组(布尔值、数字或字符串),所以可以使用上面讨论的任何深度复制技术,其中slice()和spread。。。具有最高的性能。
arr2 = arr1.slice();
arr2 = [...arr1];
arr2 = arr1.splice(0);
arr2 = arr1.concat();
arr2 = JSON.parse(JSON.stringify(arr1));
arr2 = copy(arr1); // Custom function needed, and provided above
arr2 = _.cloneDeep(arr1); // Lo-dash.js needed
arr2 = jQuery.extend(true, [], arr1); // jQuery.js needed
其他回答
不需要jQuery。。。工作示例
var arr2 = arr1.slice()
这将从起始位置0到阵列末端复制阵列。
重要的是要注意,它将按照原始类型(字符串、数字等)的预期工作,并解释引用类型的预期行为。。。
如果您有一个引用类型数组,那么就说Object类型。将复制该数组,但这两个数组都将包含对同一对象的引用。因此,在这种情况下,即使实际复制了数组,也似乎通过引用复制了数组。
使用jQuery深度复制可以如下所示:
var arr2 = $.extend(true, [], arr1);
这是我在尝试了许多方法之后所做的:
var newArray = JSON.parse(JSON.stringify(orgArray));
这将创建一个与第一个副本无关的新深度副本(而不是浅层副本)。
此外,这显然不会克隆事件和函数,但您可以在一行中完成它,并且它可以用于任何类型的对象(数组、字符串、数字、对象…)
在研究之后,我发现一个干净的方法可以是:
const arr1 = [['item 1-1', 'item 1-2'], ['item 2-1', 'item 2-2'], ['item 3-1', 'item 3-2']];
/**
* Using Spread operator, it will create a new array with no reference to the first level.
*
* Since, the items are not primitive, they get their own references. It means that any change on them,
* it will be still reflected on the original object (aka arr1).
*/
const arr2 = [...arr1];
/**
* Using Array.prototype.map() in conjunction Array.prototype.slice() will ensure:
* - The first level is not a reference to the original array.
* - In the second level, the items are forced (via slice()) to be created as new ones, so there is not reference to the original items
*/
const arr3 = arr1.map(item => item.slice());
您需要了解要使用的阵列的复杂性,然后应用最佳解决方案(即➡️ 引用数组中的引用项)
var arr2=arr1.slice(0);
这种方法只适用于简单数组。
如果您有类似复杂阵列的对象阵列,则必须使用其他解决方案,如:
const arr2 = JSON.parse(JSON.stringify(arr1));
例如,我们有一个对象数组,每个单元格的对象中都有另一个数组字段。。。在这种情况下,如果我们使用切片方法,那么数组字段将通过Ref进行复制,这意味着这些字段更新将影响原始数组中的相同元素和字段。