В 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. Старый добрый цикл for () (неглубокая копия)
Думаю, этот подход наименее популярен, учитывая, насколько модным стало функциональное программирование в наших кругах.
Чистый или нечистый, декларативный или императивный, он выполняет свою работу!
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. Старый добрый цикл while () (мелкая копия)
То же, что - 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.