Як клонувати масив у JavaScript

JavaScript має безліч способів зробити що-небудь. Я писав про 10 способів написання конвеєра / складання в JavaScript, і зараз ми робимо масиви.

1. Оператор розповсюдження (неглибока копія)

З тих пір, як ES6 впав, це був найпопулярніший метод. Це короткий синтаксис, і ви знайдете його неймовірно корисним при використанні таких бібліотек, як React та Redux.

numbers = [1, 2, 3]; numbersCopy = [...numbers]; 

Примітка. Це не дозволяє безпечно копіювати багатовимірні масиви. Значення масиву / об'єкта копіюються за посиланням, а не за значенням .

Це добре

numbersCopy.push(4); console.log(numbers, numbersCopy); // [1, 2, 3] and [1, 2, 3, 4] // numbers is left alone 

Це не добре

nestedNumbers = [[1], [2]]; numbersCopy = [...nestedNumbers]; numbersCopy[0].push(300); console.log(nestedNumbers, numbersCopy); // [[1, 300], [2]] // [[1, 300], [2]] // They've both been changed because they share references 

2. Старий добрий для () петлі (неглибока копія)

Я думаю, такий підхід є найменш популярним, враховуючи те, як модне функціональне програмування стало в наших колах.

Чистий чи нечистий, декларативний чи імперативний - це робить роботу!

numbers = [1, 2, 3]; numbersCopy = []; for (i = 0; i < numbers.length; i++) { numbersCopy[i] = numbers[i]; } 

Примітка. Це не дозволяє безпечно копіювати багатовимірні масиви. Оскільки ви використовуєте =оператор, він призначатиме об'єкти / масиви за посиланням, а не за значенням .

Це добре

numbersCopy.push(4); console.log(numbers, numbersCopy); // [1, 2, 3] and [1, 2, 3, 4] // numbers is left alone 

Це не добре

nestedNumbers = [[1], [2]]; numbersCopy = []; for (i = 0; i < nestedNumbers.length; i++) { numbersCopy[i] = nestedNumbers[i]; } numbersCopy[0].push(300); console.log(nestedNumbers, numbersCopy); // [[1, 300], [2]] // [[1, 300], [2]] // They've both been changed because they share references 

3. Старий добрий час () Петля (неглибока копія)

Те саме, що — forнечистий, імперативний, бла, бла, бла ... це працює! ?

numbers = [1, 2, 3]; numbersCopy = []; i = -1; while (++i < numbers.length) { numbersCopy[i] = numbers[i]; } 

Примітка: Це також призначає об'єкти / масиви за посиланням, а не за значенням .

Це добре

numbersCopy.push(4); console.log(numbers, numbersCopy); // [1, 2, 3] and [1, 2, 3, 4] // numbers is left alone 

Це не добре

nestedNumbers = [[1], [2]]; numbersCopy = []; i = -1; while (++i < nestedNumbers.length) { numbersCopy[i] = nestedNumbers[i]; } numbersCopy[0].push(300); console.log(nestedNumbers, numbersCopy); // [[1, 300], [2]] // [[1, 300], [2]] // They've both been changed because they share references 

4. Array.map (неглибока копія)

Повернувшись на сучасну територію, ми знайдемо цю mapфункцію. Вкорінена в математиці mapконцепція перетворення множини в інший тип множини при збереженні структури.

По-англійськи це означає, що Array.mapкожен раз повертає масив однакової довжини.

Щоб подвоїти список номерів, використовувати mapз doubleфункцією.

numbers = [1, 2, 3]; double = (x) => x * 2; numbers.map(double); 

А як щодо клонування ??

Правда, ця стаття про клонування масивів. Щоб продублювати масив, просто поверніть елемент у своєму mapдзвінку.

numbers = [1, 2, 3]; numbersCopy = numbers.map((x) => x); 

Якщо ви хочете бути трохи більш математичним, (x) => xце називається ідентичністю . Він повертає будь-який вказаний параметр.

map(identity) клонує список.

identity = (x) => x; numbers.map(identity); // [1, 2, 3] 

Примітка: Це також призначає об'єкти / масиви за посиланням, а не за значенням .

5. Array.filter (неглибока копія)

Ця функція повертає масив, як і map, але не гарантовано однакової довжини.

Що робити, якщо ви фільтруєте парні числа?

[1, 2, 3].filter((x) => x % 2 === 0); // [2] 

Вхідна довжина масиву становила 3, але отримана довжина - 1.

Якщо ваш filterпредикат завжди повертається true, ви отримуєте дублікат!

numbers = [1, 2, 3]; numbersCopy = numbers.filter(() => true); 

Кожен елемент проходить тест, тому він повертається.

Примітка: Це також призначає об'єкти / масиви за посиланням, а не за значенням .

6. Array.reduce (неглибока копія)

Мені майже reduceстає погано, коли я клоную масив, бо він набагато потужніший за це. Але ось ми йдемо ...

numbers = [1, 2, 3]; numbersCopy = numbers.reduce((newArray, element) => { newArray.push(element); return newArray; }, []); 

reduce перетворює початкове значення під час циклу по списку.

Тут початкове значення - це порожній масив, і ми заповнюємо його кожним елементом по ходу. Цей масив потрібно повернути з функції, яка буде використана в наступній ітерації.

Примітка: Це також призначає об'єкти / масиви за посиланням, а не за значенням .

7. Array.slice (неглибока копія)

sliceповертає поверхневу копію масиву на основі наданого вами індексу початку / кінця.

Якщо ми хочемо перші 3 елементи:

[1, 2, 3, 4, 5].slice(0, 3); // [1, 2, 3] // Starts at index 0, stops at index 3 

If we want all the elements, don’t give any parameters

numbers = [1, 2, 3, 4, 5]; numbersCopy = numbers.slice(); // [1, 2, 3, 4, 5] 

Note: This is a shallow copy, so it also assigns objects/arrays by reference instead of by value.

8. JSON.parse and JSON.stringify (Deep copy)

JSON.stringify turns an object into a string.

JSON.parse turns a string into an object.

Combining them can turn an object into a string, and then reverse the process to create a brand new data structure.

Note: This onesafely copies deeply nested objects/arrays!

nestedNumbers = [[1], [2]]; numbersCopy = JSON.parse(JSON.stringify(nestedNumbers)); numbersCopy[0].push(300); console.log(nestedNumbers, numbersCopy); // [[1], [2]] // [[1, 300], [2]] // These two arrays are completely separate! 

9. Array.concat (Shallow copy)

concat combines arrays with values or other arrays.

[1, 2, 3].concat(4); // [1, 2, 3, 4] [1, 2, 3].concat([4, 5]); // [1, 2, 3, 4, 5] 

If you give nothing or an empty array, a shallow copy’s returned.

[1, 2, 3].concat(); // [1, 2, 3] [1, 2, 3].concat([]); // [1, 2, 3] 

Note: This also assigns objects/arrays by reference instead of by value.

10. Array.from (Shallow copy)

This can turn any iterable object into an array. Giving an array returns a shallow copy.

numbers = [1, 2, 3]; numbersCopy = Array.from(numbers); // [1, 2, 3] 

Note: This also assigns objects/arrays by reference instead of by value.

Conclusion

Well, this was fun ?

I tried to clone using just 1 step. You’ll find many more ways if you employ multiple methods and techniques.