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.