按值复制数组

发布于 2024-12-05 15:56:51 字数 217 浏览 1 评论 0原文

当在 JavaScript 中将一个数组复制到另一个数组时:

var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d');  // Now, arr1 = ['a','b','c','d']

我意识到 arr2 引用与 arr1 相同的数组,而不是一个新的独立数组。如何复制数组以获得两个独立的数组?

When copying an array in JavaScript to another array:

var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d');  // Now, arr1 = ['a','b','c','d']

I realized that arr2 refers to the same array as arr1, rather than a new, independent array. How can I copy the array to get two independent arrays?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

空袭的梦i 2024-12-12 15:56:51

使用这个:

let oldArray = [1, 2, 3, 4, 5];

let newArray = oldArray.slice();

console.log({newArray});

基本上, slice()操作克隆数组并返回对新数组的引用。

另请注意:

对于引用、字符串和数字(​​而不是实际对象),slice() 将对象引用复制到新数组中。原始数组和新数组都引用到同一个对象。如果引用的对象发生更改,则新数组和原始数组都可以看到这些更改。

字符串和数字等基元是不可变的,因此不可能更改字符串或数字。

Use this:

let oldArray = [1, 2, 3, 4, 5];

let newArray = oldArray.slice();

console.log({newArray});

Basically, the slice() operation clones the array and returns a reference to a new array.

Also note that:

For references, strings and numbers (and not the actual object), slice() copies object references into the new array. Both the original and new array refer to the same object. If a referenced object changes, the changes are visible to both the new and original arrays.

Primitives such as strings and numbers are immutable, so changes to the string or number are impossible.

坦然微笑 2024-12-12 15:56:51

在 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 () {} ];

深度复制技术取决于三种数组类型

根据数组中元素的类型,我们可以使用各种技术进行深度复制。

深度复制技术

按元素类型划分的 Javascript 深度复制技术

基准

https://www.measurethat.net/Benchmarks/Show/17502/0/deep-copy-comparison

  • 文字值数组(type1)
    [ ...myArray ]myArray.splice(0)myArray.slice()myArray.concat( ) 技术可用于仅深度复制具有文字值(布尔值、数字和字符串)的数组;其中 slice() 在 Chrome 中具有最高性能,而 spread ... 在 Firefox 中具有最高性能。

  • 文字值(type1)和文字结构(type2)数组
    JSON.parse(JSON.stringify(myArray)) 技术可用于深度复制文字值(布尔值、数字、字符串)和文字结构(数组、对象),但不能深度复制原型对象。< /p>

  • 所有数组(type1、type2、type3)

    • structuralClone();
    • 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 相同的数组,而不是一个新的独立数组。如何复制数组以获得两个独立的数组?

code

由于 arr1 是一个文字值数组(布尔值、数字或字符串),因此您可以使用上面讨论的任何深度复制技术,其中 slice() 和 spread < >... 具有最高的性能。

arr2 = arr1.slice();
arr2 = [...arr1];
arr2 = arr1.splice(0);
arr2 = arr1.concat();
arr2 = JSON.parse(JSON.stringify(arr1));
arr2 = structuredClone(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

In Javascript, deep-copy techniques depend on the elements in an array. Let's start there.

Three types of elements

Elements can be: literal values, literal structures, or prototypes.

// 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 () {}

From these elements we can create three types of arrays.

// 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 () {} ];

Deep copy techniques depend on the three array types

Based on the types of elements in the array, we can use various techniques to deep copy.

Deep copy techniques

Javascript deep copy techniques by element types

Benchmarks

https://www.measurethat.net/Benchmarks/Show/17502/0/deep-copy-comparison

  • Array of literal-values (type1)
    The [ ...myArray ], myArray.splice(0), myArray.slice(), and myArray.concat() techniques can be used to deep copy arrays with literal values (boolean, number, and string) only; where slice() has the highest performance in Chrome, and spread ... has the highest performance in Firefox.

  • Array of literal-values (type1) and literal-structures (type2)
    The JSON.parse(JSON.stringify(myArray)) technique can be used to deep copy literal values (boolean, number, string) and literal structures (array, object), but not prototype objects.

  • All arrays (type1, type2, type3)

    • structuredClone();
    • The Lo-dash cloneDeep(myArray) or jQuery extend(true, [], myArray) techniques can be used to deep-copy all array-types. Where the Lodash cloneDeep() technique has the highest performance.
    • And for those who avoid third-party libraries, the custom function below will deep-copy all array-types, with lower performance than cloneDeep() and higher performance than 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;
}

So to answer the question...

Question

var arr1 = ['a','b','c'];
var arr2 = arr1;

I realized that arr2 refers to the same array as arr1, rather than a new, independent array. How can I copy the array to get two independent arrays?

Answer

Because arr1 is an array of literal values (boolean, number, or string), you can use any deep copy technique discussed above, where slice() and spread ... have the highest performance.

arr2 = arr1.slice();
arr2 = [...arr1];
arr2 = arr1.splice(0);
arr2 = arr1.concat();
arr2 = JSON.parse(JSON.stringify(arr1));
arr2 = structuredClone(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
汐鸠 2024-12-12 15:56:51

您可以使用数组扩展 ... 来复制数组。

const itemsCopy = [...items];

另外,如果想要创建一个新数组并将现有数组作为其中的一部分:

var parts = ['shoulders', 'knees'];
var lyrics = ['head', ...parts, 'and', 'toes'];

数组扩展现在为 所有主要浏览器均受支持,但如果您需要较旧的支持,请使用 typescript 或 babel并编译为ES5。

有关点差的更多信息

You can use array spreads ... to copy arrays.

const itemsCopy = [...items];

Also if want to create a new array with the existing one being part of it:

var parts = ['shoulders', 'knees'];
var lyrics = ['head', ...parts, 'and', 'toes'];

Array spreads are now supported in all major browsers but if you need older support use typescript or babel and compile to ES5.

More info on spreads

深海不蓝 2024-12-12 15:56:51

不需要 jQuery... 工作示例

var arr2 = arr1.slice()

这将从头开始复制数组将 0 定位到数组末尾。

重要的是要注意,它将按原始类型(字符串、数字等)的预期工作,并且还要解释引用类型的预期行为...

如果您有一个引用类型数组,例如 对象。数组被复制,但两个数组都将包含对相同对象的引用。因此,在这种情况下,即使数组实际上已被复制,数组也似乎是通过引用复制的。

No jQuery needed... Working Example

var arr2 = arr1.slice()

This copys the array from the starting position 0 through the end of the array.

It is important to note that it will work as expected for primitive types (string, number, etc.), and to also explain the expected behavior for reference types...

If you have an array of Reference types, say of type Object. The array will be copied, but both of the arrays will contain references to the same Object's. So in this case it would seem like the array is copied by reference even though the array is actually copied.

兲鉂ぱ嘚淚 2024-12-12 15:56:51

这就是我在尝试多种方法后所做的:

var newArray = JSON.parse(JSON.stringify(orgArray));

这将创建一个与第一个副本无关的新深层副本(不是浅副本)。

此外,这显然不会克隆事件和函数,但好处是您可以在一行中完成它,并且它可以用于任何类型的对象(数组、字符串、数字、对象...)

This is how I've done it after trying many approaches:

var newArray = JSON.parse(JSON.stringify(orgArray));

This will create a new deep copy not related to the first one (not a shallow copy).

Also this obviously will not clone events and functions, but the good thing you can do it in one line, and it can be used for any kind of object (arrays, strings, numbers, objects ...)

ぶ宁プ宁ぶ 2024-12-12 15:56:51

slice 的替代方案concat,有两种使用方式。第一个方法可能更具可读性,因为预期的行为非常明确:

var array2 = [].concat(array1);

第二种方法是:

var array2 = array1.concat();

Cohen(在评论中)指出后一种方法 具有更好的性能

其工作方式是,concat 方法创建一个新数组,该数组由调用它的对象中的元素组成,后跟作为参数传递给它的任何数组的元素。因此,当没有传递参数时,它只是复制数组。

Lee Penkman也在评论中指出,如果array1有可能未定义,您可以返回一个空数组,如下所示:

var array2 = [].concat(array1 || []);

或者,对于第二种方法:

var array2 = (array1 || []).concat();

注意您也可以使用 slice 执行此操作:var array2 = (array1 || []).slice();

An alternative to slice is concat, which can be used in 2 ways. The first of these is perhaps more readable as the intended behaviour is very clear:

var array2 = [].concat(array1);

The second method is:

var array2 = array1.concat();

Cohen (in the comments) pointed out that this latter method has better performance.

The way this works is that the concat method creates a new array consisting of the elements in the object on which it is called followed by the elements of any arrays passed to it as arguments. So when no arguments are passed, it simply copies the array.

Lee Penkman, also in the comments, points out that if there's a chance array1 is undefined, you can return an empty array as follows:

var array2 = [].concat(array1 || []);

Or, for the second method:

var array2 = (array1 || []).concat();

Note that you can also do this with slice: var array2 = (array1 || []).slice();.

べ映画 2024-12-12 15:56:51

重要!

这里的大多数答案都适用于特定情况

如果你不关心深层/嵌套对象和道具使用(ES6):

let clonedArray = [...array]

但如果你想进行深度克隆使用而是:

let cloneArray = JSON.parse(JSON.stringify(array))*

*使用 stringify 时,函数不会被保留(序列化),没有它们,您将得到结果。


对于lodash用户:

let clonedArray = _.clone(array) 文档

let clonedArray = _.cloneDeep(array) 文档

Important!

Most of answers here works for particular cases.

If you don't care about deep/nested objects and props use (ES6):

let clonedArray = [...array]

but if you want to do deep clone use this instead:

let cloneArray = JSON.parse(JSON.stringify(array))*

*functions won't be preserved (serialized) while using stringify, you will get result without them.


For lodash users:

let clonedArray = _.clone(array) documentation

and

let clonedArray = _.cloneDeep(array) documentation

如歌彻婉言 2024-12-12 15:56:51

我个人认为 Array.from 是更具可读性的解决方案。顺便说一下,请注意其浏览器支持。

// clone
let x = [1, 2, 3];
let y = Array.from(x);
console.log({y});

// deep clone
let clone = arr => Array.from(arr, item => Array.isArray(item) ? clone(item) : item);
x = [1, [], [[]]];
y = clone(x);
console.log({y});

I personally think Array.from is a more readable solution. By the way, just beware of its browser support.

// clone
let x = [1, 2, 3];
let y = Array.from(x);
console.log({y});

// deep clone
let clone = arr => Array.from(arr, item => Array.isArray(item) ? clone(item) : item);
x = [1, [], [[]]];
y = clone(x);
console.log({y});

半城柳色半声笛 2024-12-12 15:56:51

上面提到的一些方法在处理数字或字符串等简单数据类型时效果很好,但当数组包含其他对象时,这些方法就会失败。当我们尝试将任何对象从一个数组传递到另一个数组时,它将作为引用而不是对象传递。

在您的 JavaScript 文件中添加以下代码:

Object.prototype.clone = function() {
    var newObj = (this instanceof Array) ? [] : {};
    for (i in this) {
        if (i == 'clone') 
            continue;
        if (this[i] && typeof this[i] == "object") {
            newObj[i] = this[i].clone();
        } 
        else 
            newObj[i] = this[i]
    } return newObj;
};

只需使用

var arr1 = ['val_1','val_2','val_3'];
var arr2 = arr1.clone()

它即可工作。

Some of mentioned methods work well when working with simple data types like number or string, but when the array contains other objects these methods fail. When we try to pass any object from one array to another it is passed as a reference, not the object.

Add the following code in your JavaScript file:

Object.prototype.clone = function() {
    var newObj = (this instanceof Array) ? [] : {};
    for (i in this) {
        if (i == 'clone') 
            continue;
        if (this[i] && typeof this[i] == "object") {
            newObj[i] = this[i].clone();
        } 
        else 
            newObj[i] = this[i]
    } return newObj;
};

And simply use

var arr1 = ['val_1','val_2','val_3'];
var arr2 = arr1.clone()

It will work.

风启觞 2024-12-12 15:56:51

从ES2015开始,

var arr2 = [...arr1];

From ES2015,

var arr2 = [...arr1];
与君绝 2024-12-12 15:56:51

如果您处于 ECMAScript 6 环境中,请使用 Spread 运算符 你可以这样做是这样的:

var arr1 = ['a','b','c'];
var arr2 = [...arr1]; //copy arr1
arr2.push('d');

console.log(arr1)
console.log(arr2)
<script src="http://www.wzvang.com/snippet/ignore_this_file.js"></script>

If you are in an environment of ECMAScript 6, using the Spread Operator you could do it this way:

var arr1 = ['a','b','c'];
var arr2 = [...arr1]; //copy arr1
arr2.push('d');

console.log(arr1)
console.log(arr2)
<script src="http://www.wzvang.com/snippet/ignore_this_file.js"></script>

尤怨 2024-12-12 15:56:51

原始值始终通过其值传递(复制)。然而,复合值是通过引用传递的。

那么我们如何复制这个arr呢?

let arr = [1,2,3,4,5];

在 ES6 中复制数组

let arrCopy = [...arr]; 

在 ES5 中复制 n 数组

let arrCopy = arr.slice(); 
let arrCopy = [].concat(arr);

为什么 `let arrCopy = arr` 不是按值传递?

在复合值(例如对象/数组)上将一个变量传递给另一个变量的行为有所不同。对 copand 值使用 asign 运算符,我们传递对对象的引用。这就是为什么在删除/添加 arr 元素时两个数组的值都会发生变化的原因。

例外:

arrCopy[1] = 'adding new value this way will unreference';

当您为变量分配新值时,您正在更改引用本身,并且不会影响原始对象/数组。

了解更多

Primitive values are always pass by its value (copied). Compound values however are passed by reference.

So how do we copy this arr?

let arr = [1,2,3,4,5];

Copy an Array in ES6

let arrCopy = [...arr]; 

Copy n Array in ES5

let arrCopy = arr.slice(); 
let arrCopy = [].concat(arr);

Why `let arrCopy = arr` is not passing by value?

Passing one varible to another on Compound values such as Object/Array behave difrently. Using asign operator on copand values we pass reference to an object. This is why the value of both arrays are changing when removing/adding arr elements.

Exceptions:

arrCopy[1] = 'adding new value this way will unreference';

When you assign a new value to the variable, you are changing the reference itself and it doesn’t affect the original Object/Array.

read more

云朵有点甜 2024-12-12 15:56:51

添加到 array.slice(); 的解决方案请注意,如果您有多维数组,子数组将通过引用复制。
你可以做的是循环和切片()每个子数组单独

var arr = [[1,1,1],[2,2,2],[3,3,3]];
var arr2 = arr.slice();

arr2[0][1] = 55;
console.log(arr2[0][1]);
console.log(arr[0][1]);

function arrCpy(arrSrc, arrDis){
 for(elm in arrSrc){
  arrDis.push(arrSrc[elm].slice());
}
}

var arr3=[];
arrCpy(arr,arr3);

arr3[1][1] = 77;

console.log(arr3[1][1]);
console.log(arr[1][1]);

相同的东西进入对象数组,它们将通过引用复制,你必须手动复制它们

Adding to the solution of array.slice(); be aware that if you have multidimensional array sub-arrays will be copied by references.
What you can do is to loop and slice() each sub-array individually

var arr = [[1,1,1],[2,2,2],[3,3,3]];
var arr2 = arr.slice();

arr2[0][1] = 55;
console.log(arr2[0][1]);
console.log(arr[0][1]);

function arrCpy(arrSrc, arrDis){
 for(elm in arrSrc){
  arrDis.push(arrSrc[elm].slice());
}
}

var arr3=[];
arrCpy(arr,arr3);

arr3[1][1] = 77;

console.log(arr3[1][1]);
console.log(arr[1][1]);

same things goes to array of objects, they will be copied by reference, you have to copy them manually

迷乱花海 2024-12-12 15:56:51
let a = [1,2,3];

现在您可以执行以下任一操作来制作数组的副本。

let b = Array.from(a); 

OR

let b = [...a];

OR

let b = new Array(...a); 

OR OR

let b = a.slice(); 

OR

let b = a.map(e => e);

现在,如果我改变 a,

a.push(5); 

那么 a 是 [1,2,3,5] 但 b 仍然是 [1,2,3],因为它有不同的引用。

但我认为,在上述所有方法中 Array.from 更好,主要用于复制数组。

let a = [1,2,3];

Now you can do any one of the following to make a copy of an array.

let b = Array.from(a); 

OR

let b = [...a];

OR

let b = new Array(...a); 

OR

let b = a.slice(); 

OR

let b = a.map(e => e);

Now, if i change a,

a.push(5); 

Then, a is [1,2,3,5] but b is still [1,2,3] as it has different reference.

But i think, in all the methods above Array.from is better and made mainly to copy an array.

昵称有卵用 2024-12-12 15:56:51

我个人更喜欢这种方式:

JSON.parse(JSON.stringify( originalObject ));

I would personally prefer this way:

JSON.parse(JSON.stringify( originalObject ));
小清晰的声音 2024-12-12 15:56:51

我发现这个方法比较简单:

let arr = [1,2,3,4,5];
let newArr = [...arr];
console.log(newArr);

I found this method comparatively easier:

let arr = [1,2,3,4,5];
let newArr = [...arr];
console.log(newArr);

奶茶白久 2024-12-12 15:56:51

当有很多答案时,您必须使用最佳实践来解决此问题。

我建议您使用数组扩展...来复制数组。

var arr1 = ['a','b','c'];

var arr2 = [...arr1];

You must use best practice for this question when there are a lot of answers.

I recommend to you use array spreads … to copy arrays.

var arr1 = ['a','b','c'];

var arr2 = […arr1];

指尖微凉心微凉 2024-12-12 15:56:51

正如我们所知,在 Javascript 中数组对象是通过引用来实现的,但是我们可以通过什么方式来复制数组而不更改原始数组呢?

这里有几种方法:

想象一下我们的代码中有这个数组:

var arr = [1, 2, 3, 4, 5];

1)在函数中循环遍历数组并返回一个新数组,如下所示:

 function newArr(arr) {
      var i=0, res = [];
      while(i<arr.length){
       res.push(arr[i]);
        i++;
       }
   return res;
 }

2)使用切片方法,切片用于切片数组的一部分,它将对数组的某些部分进行切片,而不触及原始数组,在切片中,如果不指定数组的开始和结束,它将对整个数组进行切片并基本上制作数组的完整副本,因此我们可以轻松地说:

var arr2 = arr.slice(); // make a copy of the original array

3)还有联系方式,这是用于合并两个数组,但我们可以只指定其中一个数组,然后这基本上会复制新接触的数组中的值:

var arr2 = arr.concat();

4)还有 stringify 和 parse 方法,不推荐,但可以是复制数组的简单方法和 Objects:

var arr2 = JSON.parse(JSON.stringify(arr));

5) Array.from 方法,这个没有被广泛支持,使用前检查不同浏览器的支持:

const arr2 = Array.from(arr);

6) ECMA6 方式,也没有完全支持,但是如果你想转译,babelJs 可以帮助你:

const arr2 = [...arr];

As we know in Javascript arrays and objects are by reference, but what ways we can do copy the array without changing the original array later one?

Here are few ways to do it:

Imagine we have this array in your code:

var arr = [1, 2, 3, 4, 5];

1) Looping through the array in a function and return a new array, like this:

 function newArr(arr) {
      var i=0, res = [];
      while(i<arr.length){
       res.push(arr[i]);
        i++;
       }
   return res;
 }

2) Using slice method, slice is for slicing part of the array, it will slice some part of your array without touching the original, in the slice, if don't specify the start and end of the array, it will slice the whole array and basically make a full copy of the array, so we can easily say:

var arr2 = arr.slice(); // make a copy of the original array

3) Also contact method, this is for merging two array, but we can just specify one of arrays and then this basically make a copy of the values in the new contacted array:

var arr2 = arr.concat();

4) Also stringify and parse method, it's not recommended, but can be an easy way to copy Array and Objects:

var arr2 = JSON.parse(JSON.stringify(arr));

5) Array.from method, this is not widely supported, before use check the support in different browsers:

const arr2 = Array.from(arr);

6) ECMA6 way, also not fully supported, but babelJs can help you if you want to transpile:

const arr2 = [...arr];
幼儿园老大 2024-12-12 15:56:51

您可以将 ES6 与扩展 Opeartor 一起使用,它更简单。

arr2 = [...arr1];

有限制..检查文档传播语法@ mozilla

You could use ES6 with spread Opeartor, its simpler.

arr2 = [...arr1];

There are limitations..check docs Spread syntax @ mozilla

醉酒的小男人 2024-12-12 15:56:51

丹,没必要用什么花招。您所需要做的就是通过执行此操作来复制 arr1 。

var arr1 = ['a','b','c'];
var arr2 = [];

var arr2 = new Array(arr1);

arr2.push('d');  // Now, arr2 = [['a','b','c'],'d']

console.log('arr1:');
console.log(arr1);

console.log('arr2:');
console.log(arr2);

// Following did the trick:
var arr3 = [...arr1];
arr3.push('d');  // Now, arr3 = ['a','b','c','d'];

console.log('arr3:');
console.log(arr3);

现在,arr1 和 arr2 是两个不同的数组变量,存储在单独的堆栈中。
在 jsfiddle 上查看

Dan, no need to use fancy tricks. All you need to do is make copy of arr1 by doing this.

var arr1 = ['a','b','c'];
var arr2 = [];

var arr2 = new Array(arr1);

arr2.push('d');  // Now, arr2 = [['a','b','c'],'d']

console.log('arr1:');
console.log(arr1);

console.log('arr2:');
console.log(arr2);

// Following did the trick:
var arr3 = [...arr1];
arr3.push('d');  // Now, arr3 = ['a','b','c','d'];

console.log('arr3:');
console.log(arr3);

Now arr1 and arr2 are two different array variables stored in separate stacks.
Check this out on jsfiddle.

转角预定愛 2024-12-12 15:56:51

var arr2 = arr1.slice(0);

这样适用于简单数组

如果您有复杂数组,例如对象数组,那么您必须使用其他解决方案,例如:

const arr2 = JSON.parse(JSON.stringify(arr1)); 

例如,我们有一个对象数组,每个单元格在其对象中有另一个数组字段...在这种情况下,如果我们使用slice方法,那么数组字段将通过Ref复制 这意味着这些字段更新影响原始数组的相同元素和字段。

var arr2 = arr1.slice(0);

This way just work for simple Arrays.

If you have Complex Array like array of Objects then you must use another solutions like:

const arr2 = JSON.parse(JSON.stringify(arr1)); 

For example, we have an array of objects that each cell have another array field in its object ... in this situation if we use slice method then the array fields will copy by Ref and that's mean these fields updates will affect on orginal array same element and fields.

梦旅人picnic 2024-12-12 15:56:51

StructuredClone

在 JavaScript 中按值复制数组的现代方法是使用 结构化克隆

var arr1 = ['a', 'b', 'c'];
var arr2 = structuredClone(arr1); //copy arr1
arr2.push('d');

console.log(arr1); //a,b,c
console.log(arr2); //a,b,c,d

structuredClone

The modern way to copy array by value in JavaScript is to use structuredClone:

var arr1 = ['a', 'b', 'c'];
var arr2 = structuredClone(arr1); //copy arr1
arr2.push('d');

console.log(arr1); //a,b,c
console.log(arr2); //a,b,c,d

夜雨飘雪 2024-12-12 15:56:51

在我的特殊情况下,我需要确保阵列保持完整,所以这对我有用:

// Empty array
arr1.length = 0;
// Add items from source array to target array
for (var i = 0; i < arr2.length; i++) {
    arr1.push(arr2[i]);
}

In my particular case I needed to ensure the array remained intact so this worked for me:

// Empty array
arr1.length = 0;
// Add items from source array to target array
for (var i = 0; i < arr2.length; i++) {
    arr1.push(arr2[i]);
}
葬シ愛 2024-12-12 15:56:51

复制多维数组/对象:

function deepCopy(obj) {
   if (Object.prototype.toString.call(obj) === '[object Array]') {
      var out = [], i = 0, len = obj.length;
      for ( ; i < len; i++ ) {
         out[i] = arguments.callee(obj[i]);
      }
      return out;
   }
   if (typeof obj === 'object') {
      var out = {}, i;
      for ( i in obj ) {
         out[i] = arguments.callee(obj[i]);
      }
      return out;
   }
   return obj;
}

感谢 James Padolsey 提供此功能。

来源:此处

Make copy of multidimensional array/object:

function deepCopy(obj) {
   if (Object.prototype.toString.call(obj) === '[object Array]') {
      var out = [], i = 0, len = obj.length;
      for ( ; i < len; i++ ) {
         out[i] = arguments.callee(obj[i]);
      }
      return out;
   }
   if (typeof obj === 'object') {
      var out = {}, i;
      for ( i in obj ) {
         out[i] = arguments.callee(obj[i]);
      }
      return out;
   }
   return obj;
}

Thanks to James Padolsey for this function.

Source: Here

烟若柳尘 2024-12-12 15:56:51

如果您的数组包含原始数据类型的元素,例如int、char或string等,那么您可以使用返回原始数组副本的这些方法之一,例如作为 .slice() 或 .map() 或扩展运算符(感谢 ES6)。

new_array = old_array.slice()

new_array = old_array.map((elem) => elem)

const new_array = new Array(...old_array);

但是如果您的数组包含复杂元素,例如对象(或数组)或更多嵌套对象,那么,您必须确保您正在复制从顶层到最后一层的所有元素,否则将使用内部对象的引用,这意味着更改 new_array 中的 object_elements 中的值仍然会影响 old_array 。您可以将这种在每个级别进行复制的方法称为深度复制
old_array 的。

对于深复制,您可以根据数据类型在每个级别对原始数据类型使用上述方法,或者您可以使用这种昂贵的方法(下面提到)来进行深复制,而无需执行很多工作。

var new_array = JSON.parse(JSON.stringify(old_array));

还有很多其他方法,您可以根据自己的要求使用。我只提到了其中的一些内容,以便让我们大致了解当我们尝试按值将一个数组复制到另一个数组时会发生什么。

If your array contains elements of the primitive data type such as int, char, or string etc then you can user one of those methods which returns a copy of the original array such as .slice() or .map() or spread operator(thanks to ES6).

new_array = old_array.slice()

or

new_array = old_array.map((elem) => elem)

or

const new_array = new Array(...old_array);

BUT if your array contains complex elements such as objects(or arrays) or more nested objects, then, you will have to make sure that you are making a copy of all the elements from the top level to the last level else reference of the inner objects will be used and that means changing values in object_elements in new_array will still affect the old_array. You can call this method of copying at each level as making a DEEP COPY
of the old_array.

For deep copying, you can use the above-mentioned methods for primitive data types at each level depending upon the type of data or you can use this costly method(mentioned below) for making a deep copy without doing much work.

var new_array = JSON.parse(JSON.stringify(old_array));

There are a lot of other methods out there which you can use depending on your requirements. I have mentioned only some of those for giving a general idea of what happens when we try to copy an array into the other by value.

美煞众生 2024-12-12 15:56:51

如果要创建对象或数组的新副本,则必须显式复制该对象的属性或数组的元素,例如:

var arr1 = ['a','b','c'];
var arr2 = [];

for (var i=0; i < arr1.length; i++) {
   arr2[i] = arr1[i];
}

您可以在 Google 上搜索有关不可变原始值和可变对象引用的更多信息。

If you want to make a new copy of an object or array, you must explicitly copy the properties of the object or the elements of the array, for example:

var arr1 = ['a','b','c'];
var arr2 = [];

for (var i=0; i < arr1.length; i++) {
   arr2[i] = arr1[i];
}

You can search for more information on Google about immutable primitive values and mutable object references.

月亮是我掰弯的 2024-12-12 15:56:51

当我们想要使用赋值运算符( = )复制数组时,它不会创建副本,它只是复制指向数组的指针/引用。例如:

const oldArr = [1,2,3];

const newArr = oldArr;  // now oldArr points to the same place in memory 

console.log(oldArr === newArr);  // Points to the same place in memory thus is true

const copy = [1,2,3];

console.log(copy === newArr);  // Doesn't point to the same place in memory and thus is false

通常,当我们转换数据时,我们希望保持初始数据结构(例如数组)完整。我们通过制作数组的精确副本来做到这一点,这样就可以在第一个数组保持不变的情况下对其进行转换。

复制数组的方法:

const oldArr = [1,2,3];

// Uses the spread operator to spread out old values into the new array literal
const newArr1 = [...oldArr];

// Slice with no arguments returns the newly copied Array
const newArr2 = oldArr.slice();

// Map applies the callback to every element in the array and returns a new array
const newArr3 = oldArr.map((el) => el);

// Concat is used to merge arrays and returns a new array. Concat with no args copies an array
const newArr4 = oldArr.concat();

// Object.assign can be used to transfer all the properties into a new array literal
const newArr5 = Object.assign([], oldArr);

// Creating via the Array constructor using the new keyword
const newArr6 = new Array(...oldArr);

// For loop
function clone(base) {
	const newArray = [];
    for(let i= 0; i < base.length; i++) {
	    newArray[i] = base[i];
	}
	return newArray;
}

const newArr7 = clone(oldArr);

console.log(newArr1, newArr2, newArr3, newArr4, newArr5, newArr6, newArr7);

嵌套数组或对象时要小心!:

当嵌套数组时,值将通过引用复制。以下是这可能如何导致问题的示例:

let arr1 = [1,2,[1,2,3]]

let arr2 = [...arr1];

arr2[2][0] = 5;  // we change arr2

console.log(arr1);  // arr1 is also changed because the array inside arr1 was copied by reference

因此,当您要复制的数组中有对象或数组时,请勿使用这些方法。即仅对基元数组使用这些方法。

如果您确实想深度克隆 javascript 数组,请结合使用 JSON.parseJSON.stringify,如下所示:

let arr1 = [1,2,[1,2,3]]

let arr2 = JSON.parse(JSON.stringify(arr1)) ;

arr2[2][0] = 5;

console.log(arr1);  // now I'm not modified because I'm a deep clone

复印性能:

那么我们应该选择哪一种才能获得最佳性能。事实证明,最详细的方法,for 循环具有最高的性能。使用 for 循环进行真正的 CPU 密集型复制(大型/多个数组)。

之后,.slice() 方法也具有不错的性能,并且更简洁,更容易程序员实现。我建议使用 .slice() 来日常复制对 CPU 要求不高的数组。如果不需要深度克隆并且性能是一个问题,还要避免使用 JSON.parse(JSON.stringify(arr)) (大量开销)。

源性能测试

When we want to copy an array using the assignment operator ( = ) it doesn't create a copy it merely copies the pointer/reference to the array. For example:

const oldArr = [1,2,3];

const newArr = oldArr;  // now oldArr points to the same place in memory 

console.log(oldArr === newArr);  // Points to the same place in memory thus is true

const copy = [1,2,3];

console.log(copy === newArr);  // Doesn't point to the same place in memory and thus is false

Often when we transform data we want to keep our initial datastructure (e.g. Array) intact. We do this by making a exact copy of our array so this one can be transformed while the initial one stays intact.

Ways of copying an array:

const oldArr = [1,2,3];

// Uses the spread operator to spread out old values into the new array literal
const newArr1 = [...oldArr];

// Slice with no arguments returns the newly copied Array
const newArr2 = oldArr.slice();

// Map applies the callback to every element in the array and returns a new array
const newArr3 = oldArr.map((el) => el);

// Concat is used to merge arrays and returns a new array. Concat with no args copies an array
const newArr4 = oldArr.concat();

// Object.assign can be used to transfer all the properties into a new array literal
const newArr5 = Object.assign([], oldArr);

// Creating via the Array constructor using the new keyword
const newArr6 = new Array(...oldArr);

// For loop
function clone(base) {
	const newArray = [];
    for(let i= 0; i < base.length; i++) {
	    newArray[i] = base[i];
	}
	return newArray;
}

const newArr7 = clone(oldArr);

console.log(newArr1, newArr2, newArr3, newArr4, newArr5, newArr6, newArr7);

Be careful when arrays or objects are nested!:

When arrays are nested the values are copied by reference. Here is an example of how this could lead to issues:

let arr1 = [1,2,[1,2,3]]

let arr2 = [...arr1];

arr2[2][0] = 5;  // we change arr2

console.log(arr1);  // arr1 is also changed because the array inside arr1 was copied by reference

So don't use these methods when there are objects or arrays inside your array you want to copy. i.e. Use these methods on arrays of primitives only.

If you do want to deepclone a javascript array use JSON.parse in conjunction with JSON.stringify, like this:

let arr1 = [1,2,[1,2,3]]

let arr2 = JSON.parse(JSON.stringify(arr1)) ;

arr2[2][0] = 5;

console.log(arr1);  // now I'm not modified because I'm a deep clone

Performance of copying:

So which one do we choose for optimal performance. It turns out that the most verbose method, the for loop has the highest performance. Use the for loop for really CPU intensive copying (large/many arrays).

After that the .slice() method also has decent performance and is also less verbose and easier for the programmer to implement. I suggest to use .slice() for your everyday copying of arrays which aren't very CPU intensive. Also avoid using the JSON.parse(JSON.stringify(arr)) (lots of overhead) if no deep clone is required and performance is an issue.

Source performance test

人心善变 2024-12-12 15:56:51

使用 jQuery 深层复制可以如下进行:

var arr2 = $.extend(true, [], arr1);

Using jQuery deep copy could be made as following:

var arr2 = $.extend(true, [], arr1);
-柠檬树下少年和吉他 2024-12-12 15:56:51

您还可以使用 ES6 扩展运算符来复制数组

var arr=[2,3,4,5];
var copyArr=[...arr];

You can also use ES6 spread operator to copy Array

var arr=[2,3,4,5];
var copyArr=[...arr];
我不咬妳我踢妳 2024-12-12 15:56:51

这里还有几种复制方法:

const array = [1,2,3,4];

const arrayCopy1 = Object.values(array);
const arrayCopy2 = Object.assign([], array);
const arrayCopy3 = array.map(i => i);
const arrayCopy4 = Array.of(...array );

Here are few more way to copy:

const array = [1,2,3,4];

const arrayCopy1 = Object.values(array);
const arrayCopy2 = Object.assign([], array);
const arrayCopy3 = array.map(i => i);
const arrayCopy4 = Array.of(...array );

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文