Скопировать массив по значению - PullRequest
1575 голосов
/ 20 сентября 2011

При копировании массива в JavaScript в другой массив:

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

Я понял, что arr2 относится к тому же массиву, что и arr1, а не к новому независимому массиву. Как я могу скопировать массив, чтобы получить два независимых массива?

Ответы [ 33 ]

2 голосов
/ 20 сентября 2011

Если вы хотите сделать новую копию объекта или массива, вы должны явно скопировать свойства объекта или элементов массива, например:

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

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

Вы можете искать большеинформация в Google об неизменных значениях примитивов и ссылках на изменяемые объекты.

2 голосов
/ 12 января 2017

Используя глубокое копирование jQuery, можно сделать следующее:

var arr2 = $.extend(true, [], arr1);
2 голосов
/ 11 сентября 2018

Быстрые примеры:

  1. Если элементы в массиве примитивных типов (строка, число и т. Д.)

var arr1 = ['a','b','c'];
// arr1 and arr2 are independent and primitive elements are stored in 
// different places in the memory
var arr2 = arr1.slice(); 
arr2.push('d');
console.log(arr1); // [ 'a', 'b', 'c' ]
console.log(arr2); // [ 'a', 'b', 'c', 'd' ]
Если элементы в массиве являются объектными литералами, другой массив ({}, [])

var arr1 = [{ x: 'a', y: 'b'}, [1, 2], [3, 4]];
// arr1 and arr2 are independent and reference's/addresses are stored in different
// places in the memory. But those reference's/addresses points to some common place
// in the memory.
var arr2 = arr1.slice(); 
arr2.pop();      // OK - don't affect arr1 bcos only the address in the arr2 is
                 // deleted not the data pointed by that address
arr2[0].x = 'z'; // not OK - affect arr1 bcos changes made in the common area 
                 // pointed by the addresses in both arr1 and arr2
arr2[1][0] = 9;	 // not OK - same above reason

console.log(arr1); // [ { x: 'z', y: 'b' }, [ 9, 2 ], [ 3, 4 ] ]
console.log(arr2); // [ { x: 'z', y: 'b' }, [ 9, 2 ] ]
Решение для 2 : глубокое копирование от элемента к элементу

var arr1 = [{ x: 'a', y: 'b'}, [1, 2], [3, 4]];
arr2 = JSON.parse(JSON.stringify(arr1));
arr2.pop();	  // OK - don't affect arr1
arr2[0].x = 'z';  // OK - don't affect arr1
arr2[1][0] = 9;	  // OK - don't affect arr1

console.log(arr1); // [ { x: 'a', y: 'b' }, [ 1, 2 ], [ 3, 4 ] ]
console.log(arr2); // [ { x: 'z', y: 'b' }, [ 9, 2 ] ]
2 голосов
/ 18 ноября 2018
let a = [1,2,3];

Теперь вы можете выполнить любое из следующих действий, чтобы сделать копию массива.

let b = Array.from(a); 

ИЛИ

let b = [...a];

ИЛИ

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

ИЛИ

let b = a.slice(); 

ИЛИ

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

Теперь, если я изменю a,

a.push(5); 

Тогда a будет [1,2,3,5] но b по-прежнему [1,2,3], так как имеет другую ссылку.

Но я думаю, что во всех описанных выше методах Array.from лучше и сделан в основном для копирования массива.

1 голос
/ 31 декабря 2018

Примитивные значения всегда передаются по его значению (копируются). Составные значения, однако, передаются по ссылке.

Так, как мы копируем этот arr?

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

Копирование массива в ES6

let arrCopy = [...arr]; 

Копировать массив в ES5

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

Почему `let arrCopy = arr` не передается по значению?

Передача одной переменной в другую по составным значениям, таким как объект / массив, ведет себя по-разному. Используя оператор asign для значений copand, мы передаем ссылку на объект. Вот почему значение обоих массивов изменяется при удалении / добавлении элементов arr.

Исключения:

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

Когда вы присваиваете новое значение переменной, вы изменяете саму ссылку, и она не влияет на исходный объект / массив.

читать больше

1 голос
/ 13 декабря 2018

Вот как вы можете это сделать для массива массивов примитивов переменной глубины:

// If a is array: 
//    then call cpArr(a) for each e;
//    else return a

const cpArr = a => Array.isArray(a) && a.map(e => cpArr(e)) || a;

let src = [[1,2,3], [4, ["five", "six", 7], true], 8, 9, false];
let dst = cpArr(src);

https://jsbin.com/xemazog/edit?js,console

1 голос
/ 06 октября 2013

Вот вариант:

var arr1=['a', 'b', 'c'];
var arr2=eval(arr1.toSource());
arr2.push('d');
console.log('arr1: '+arr1+'\narr2: '+arr2);
/*
 *  arr1: a,b,c
 *  arr2: a,b,c,d
 */
1 голос
/ 10 декабря 2014

Это недавно представленная Array.from, но, к сожалению, на момент написания этой статьи она поддерживается только в последних версиях Firefox (32 и выше). Его можно просто использовать следующим образом:

var arr1 = [1, 2, 3];
console.log(Array.from(arr1)); // Logs: [1, 2, 3]

Ссылка: Здесь

Или Array.prototype.map может использоваться с функцией идентификации:

function identity(param)
{
    return param;
}

var arr1 = [1, 2, 3],
    clone = arr1.map(identity);

Ссылка: Здесь

1 голос
/ 27 июня 2018

Вы можете использовать ES6 с распространением Opeartor, это проще.

arr2 = [...arr1];

Существуют ограничения ... проверьте документы Синтаксис распространения @ mozilla

1 голос
/ 31 мая 2018

Вы можете сделать это следующим образом:
arr2 = arr1.map(x => Object.assign({}, x));

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...