Копировать массив по значению

1493

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

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

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

  • 2
    Похоже, что в настоящее время в Chrome 53 и Firefox 48 мы имеем отличную производительность для операций slice и splice а новый оператор распространения и Array.from имеют гораздо более медленную реализацию. Посмотрите на perfjs.fnfo
  • 0
    jsben.ch/#/wQ9RU <= этот тест дает обзор различных способов копирования массива
Показать ещё 5 комментариев
Теги:
arrays

32 ответа

2371
Лучший ответ

Использовать этот:

var newArray = oldArray.slice();

В принципе, операция slice() клонирует массив и возвращает ссылку на новый массив. Также обратите внимание:

Для ссылок, строк и чисел (а не фактического объекта), slice() копирует ссылки на объекты в новый массив. И исходный, и новый массив относятся к одному и тому же объекту. Если объект, на который ссылается, изменяется, изменения видны как для нового, так и для оригинального массива.

Примитивы, такие как строки и числа, неизменяемы, поэтому изменения строки или числа невозможно.

  • 9
    Что касается производительности, следующие тесты jsPerf на самом деле показывают, что var arr2 = arr1.slice () работает так же быстро, как var arr2 = arr1.concat (); JSPerf: jsperf.com/copy-array-slice-vs-concat/5 и jsperf.com/copy-simple-array . Результат jsperf.com/array-copy/5 отчасти удивил меня, и мне стало интересно, действительно ли тестовый код действителен.
  • 87
    Несмотря на то, что это уже получило массу голосов, оно заслуживает другого, поскольку правильно описывает ссылки в JS, что, к сожалению, довольно редко.
Показать ещё 8 комментариев
427

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

Методы глубокого копирования зависят от трех типов массивов

Основываясь на типах элементов в массиве, мы можем использовать различные методы для глубокого копирования.

Изображение 2137

  • Массив литеральных значений (type1)
    [...myArray], myArray.splice(0), myArray.slice() и myArray.concat() можно использовать только для глубокого копирования массивов только с литеральными значениями (логические, числа и строки); где оператор Spread [...myArray] имеет наилучшую производительность (https://measurethat.net/Benchmarks/Show/4281/0/spread-array-performance-vs-slice-splice-concat).

  • Массив литеральных значений (тип1) и литеральных структур (тип2)
    JSON.parse(JSON.stringify(myArray)) может использоваться для глубокого копирования литеральных значений (логических, чисел, строк) и литеральных структур (массив, объект), но не объектов-прототипов.

  • Все массивы (тип1, тип2, тип3)
    $.extend(myArray) jQuery $.extend(myArray) может использоваться для глубокого копирования всех типов массивов. Такие библиотеки, как Underscore и Lo-dash, предлагают функции глубокого копирования, аналогичные jQuery $.extend(), но имеют более низкую производительность. Еще более удивительно, что $.extend() имеет более высокую производительность, чем метод JSON.parse(JSON.stringify(myArray)) http://jsperf.com/js-deep-copy/15.
    И для тех разработчиков, которые избегают сторонних библиотек (таких как jQuery), вы можете использовать следующую пользовательскую функцию; который имеет более высокую производительность, чем $.extend, и копирует все массивы.

function copy(aObject) {
  if (!aObject) {
    return aObject;
  }

  let v;
  let bObject = Array.isArray(aObject) ? [] : {};
  for (const k in aObject) {
    v = aObject[k];
    bObject[k] = (typeof v === "object") ? copy(v) : v;
  }

  return bObject;
}

Итак, чтобы ответить на вопрос...

Вопрос

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

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

Ответ

Поскольку arr1 является массивом литеральных значений (логических, arr1 или строковых), вы можете использовать любую методику глубокого копирования, рассмотренную выше, где оператор распространения ... имеет наивысшую производительность.

// Highest performance for deep copying literal values
arr2 = [...arr1];

// Any of these techniques will deep copy literal values as well,
//   but with lower performance.
arr2 = arr1.slice();
arr2 = arr1.splice(0);
arr2 = arr1.concat();
arr2 = JSON.parse(JSON.stringify(arr1));
arr2 = $.extend(true, [], arr1); // jQuery.js needed
arr2 = _.extend(arr1); // Underscore.js needed
arr2 = _.cloneDeep(arr1); // Lo-dash.js needed
arr2 = copy(arr1); // Custom-function needed - as provided above
  • 1
    Многие из этих подходов не работают. Использование оператора присваивания означает, что вы должны переназначить исходное литеральное значение arr1 . Это очень редко, что это будет иметь место. Использование splice уничтожает arr1 , так что это не копия вообще. Использовать JSON не удастся, если какое-либо из значений в массиве будет функцией или имеет прототипы (например, Date ).
  • 0
    Использование сращивания является частичным решением. Это потерпит неудачу при гораздо большем количестве случаев, чем JSON. Splice создает глубокую копию строк и чисел, когда он перемещает значения - никогда не говорил, что возвращает копию.
Показать ещё 4 комментария
159

Вы можете использовать массивные спреды ... для копирования массивов.

const itemsCopy = [...items];

Также, если вы хотите создать новый массив с существующим, являющимся его частью:

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

Распространение массивов теперь поддерживается во всех основных браузерах, но если вам нужна более старая поддержка, используйте typescript или babel и скомпилируйте ES5.

Дополнительная информация о спредах

143

Нет необходимости в jQuery... Рабочий пример

var arr2 = arr1.slice()

Это копирует массив из начальной позиции 0 через конец массива.

Важно отметить, что он будет работать как ожидалось для примитивных типов (строка, число и т.д.), а также объяснить ожидаемое поведение для ссылочных типов...

Если у вас есть массив ссылочных типов, например типа Object. Массив будет скопирован, но оба массива будут содержать ссылки на те же Object. Таким образом, в этом случае кажется, что массив копируется по ссылке, даже если массив фактически скопирован.

  • 10
    Нет, это не будет глубокой копией.
  • 0
    Попробуй это; var arr2 = JSON.stringify(arr1); arr2 = JSON.parse(arr2);
66

Альтернативой slice является concat, который можно использовать двумя способами. Первое из них, возможно, более читаемо, поскольку предполагаемое поведение очень ясно:

var array2 = [].concat(array1);

Второй способ:

var array2 = array1.concat();

Коэн (в комментариях) указал, что этот последний метод имеет лучшую производительность.

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

Ли Пенкман, также в комментариях, указывает, что если есть шанс array1 undefined, вы можете вернуть пустой массив следующим образом:

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

Или, для второго метода:

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

Обратите внимание, что вы также можете сделать это с помощью slice: var array2 = (array1 || []).slice();.

  • 31
    На самом деле вы также можете сделать: var array2 = array1.concat (); Это намного быстрее в отношении производительности. (JSPerf: jsperf.com/copy-simple-array и jsperf.com/copy-array-slice-vs-concat/5
  • 4
    Стоит отметить, что если array1 не является массивом, то [].concat(array1) возвращает [array1] например, если он не определен, вы получите [undefined] . Я иногда делаю var array2 = [].concat(array1 || []);
52

Вот как я это сделал после нескольких попыток:

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

Это создаст новую глубокую копию, не связанную с первой (не мелкой копией).

Также это, очевидно, не будет клонировать события и функции, но хорошо, что вы можете сделать это в одной строке, и его можно использовать для любого объекта (массивы, строки, числа, объекты...)

  • 3
    Это самый лучший. Я давно использую тот же метод и думаю, что в рекурсивных циклах старой школы больше нет смысла
  • 1
    Имейте в виду, что эта опция плохо обрабатывает графоподобные структуры: происходит сбой при наличии циклов и не сохраняет общие ссылки.
Показать ещё 6 комментариев
18

Некоторые из упомянутых методов хорошо работают при работе с простыми типами данных, такими как число или строка, но когда массив содержит другие объекты, эти методы терпят неудачу. Когда мы пытаемся передать любой объект из одного массива в другой, он передается как ссылка, а не объект.

Добавьте следующий код в свой файл 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()

Он будет работать.

  • 2
    я получаю эту ошибку, когда добавляю этот код на мою страницу «Uncaught RangeError: Превышен максимальный размер стека вызовов»
  • 0
    В каком браузере вы видели эту ошибку ??
Показать ещё 6 комментариев
15

Из ES2015,

var arr2 = [...arr1];
14

Я лично считаю Array.from более читаемым решением. Кстати, просто остерегайтесь поддержки браузера.

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

//deep clone
let clone = arr => Array.from(arr,item => Array.isArray(item) ? clone(item) : item);
let x = [1,[],[[]]];
let y = clone(x);
  • 1
    Да, это очень читабельно. Решение .slice() совершенно не .slice() . Спасибо за это.
12

Важный!

Большинство ответов здесь работает для конкретных случаев.

Если вам не нужны глубокие/вложенные объекты и реквизиты (ES6):

let clonedArray = [...array]

но если вы хотите сделать глубокий клон, используйте это вместо этого:

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


Для пользователей lodash:

let clonedArray = _.clone(array) документация

а также

let clonedArray = _.cloneDeep(array) документация

11

Если вы находитесь в среде 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>
9

Добавляя к решению array.slice();, помните, что если у вас есть многомерный массив, подмассивы будут скопированы по ссылкам. То, что вы можете сделать, это loop и 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]);

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

  • 0
    Этот ответ заслуживает места в верхней части страницы! Я работал с многомерными вложенными массивами и не мог понять, почему внутренние массивы всегда копировались с помощью ref, а не val. Эта простая логика решила мою проблему. Я бы дал вам +100, если это возможно!
6

Как мы знаем в массивах 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 не рекомендуется, но может быть простым способом для копирования массива и объектов:

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

5) Метод Array.from, это широко не поддерживается, перед использованием проверьте поддержку в разных браузерах:

const arr2 = Array.from(arr);

6) ECMA6, также не полностью поддерживается, но babelJs может помочь вам, если вы хотите перекрыть:

const arr2 = [...arr];
4

Дэн, не нужно использовать причудливые трюки. Все, что вам нужно сделать, это сделать копию arr1, выполнив это.

var arr2 = new Array(arr1);

Теперь arr1 и arr2 - две разные переменные массива, хранящиеся в отдельных стеках. Проверьте это на jsfiddle.

  • 0
    Это не копирует массив. Он создает массив с одним элементом, который ссылается на оригинал (т.е. var arr2 = [arr1]; ).
4

Сделать копию многомерного массива/объекта:

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;
}

Спасибо Джеймсу Падолси за эту функцию.

Источник: Здесь

  • 1
    Хорошо, помог мне. благодарю вас.
  • 0
    Большое спасибо, сэр
4

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

// 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]);
}
  • 2
    +1 за то, что вы не добавили мрачность в свой код, вызвав функцию, которая делает то же самое, но менее очевидным способом. slice может быть более эффективным под капотом, но для всех, кто работает над кодом, это показывает ваше намерение. Кроме того, это упрощает оптимизацию позже, если вы хотите (например) фильтровать то, что копируете. обратите внимание, однако, что это не обрабатывает глубокое копирование, и те же самые внутренние объекты передаются в новый массив, по ссылке. Это может быть то, что вы хотите сделать, а может и нет.
3

Когда мы хотим скопировать массив с помощью оператора присваивания (=), он не создает копию, он просто копирует указатель/ссылку на массив. Например:

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.parse в сочетании с JSON.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 циклы для очень интенсивной загрузки процессора копирования (большие/много массивов).

После этого метод .slice() также имеет достойную производительность, а также менее подробный и простой для программиста. Я предлагаю использовать .slice() для ежедневного копирования массивов, которые не очень интенсивно работают с ЦП. Также избегайте использования JSON.parse(JSON.stringify(arr)) (много накладных расходов), если не требуется глубокий клон и проблема с производительностью.

Тест производительности источника

2

Если ваш массив содержит элементы примитивного типа данных, такие как 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 все равно будет влиять на old_array. Вы можете вызвать этот метод копирования на каждом уровне, сделав DEEP COPY для old_array.

Для глубокого копирования вы можете использовать вышеупомянутые методы для примитивных типов данных на каждом уровне в зависимости от типа данных, или вы можете использовать этот дорогостоящий метод (упомянутый ниже) для создания глубокой копии без большой работы.

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

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

2

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

  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' ]
  1. Если элементы массива являются объектными литералами, другой массив ({}, [])

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 ] ]
  1. Решение для 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

Вот еще несколько способов копирования:

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

const arrayCopy1 = Object.values ​​(массив);
const arrayCopy2 = Object.assign([], array);
const arrayCopy3 = ​​array.map(i = > i);
const arrayCopy4 = Array.of(... array);
2

Вы также можете использовать оператор распространения ES6 для копирования Array

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

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

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

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

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

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

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

  • 1
    Вам не нужно явно копировать свойства объектов массива. Смотрите ответ Чтиви Малек.
1
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.push(5); 

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

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

1

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

arr2 = [...arr1];

Существуют ограничения..check docs Распространение синтаксиса @mozilla

1

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

1

Там появился новый 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);

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

  • 0
    +1 за упоминание Array.from , который теперь поддерживается во всех основных браузерах, кроме Internet Explorer ( источник ). ,
1

Здесь вариант:

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
 */
  • 0
    неплохая идея, хотя я бы лучше использовал JSON stringify / parse вместо eval, и было бы неплохо проверить еще одно сравнение jsPerf, также обратите внимание, что toSource не является стандартным и не будет работать, например, в Chrome.
0

Просто пишу:

arr2 = arr1.concat();

Вы генерируете новый новый массив с копией первого. Помните, что это функциональный способ поместить элемент в массив.

Если ваш код основан на ES6, вы также можете использовать оператор распространения:

arr2 = [...arr1];
0

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

Так, как мы копируем этот 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.

Exceptios:

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

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

прочитайте больше

0

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

// 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

0

Для массива ES6, содержащего объекты

cloneArray(arr) {
    return arr.map(x => ({ ...x }));
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню