Ever since ES6 dropped, this has been the most popular method. It’s a brief syntax and you’ll find it incredibly useful when using libraries like React and Redux.
numbers = [1, 2, 3];
numbersCopy = [...numbers];
Note: This doesn’t safely copy multi-dimensional arrays. Array/object values are copied by reference instead of by value.
This is fine
numbersCopy.push(4);
console.log(numbers, numbersCopy);
// [1, 2, 3] and [1, 2, 3, 4]
// numbers is left alone
This is not fine
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
I imagine this approach is the least popular, given how trendy functional programming’s become in our circles.
Pure or impure, declarative or imperative, it gets the job done!
numbers = [1, 2, 3];
numbersCopy = [];
for (i = 0; i < numbers.length; i++) {
numbersCopy[i] = numbers[i];
}
Note: This doesn’t safely copy multi-dimensional arrays. Since you’re using the =
operator, it’ll assign objects/arrays by reference instead of by value.
This is fine
numbersCopy.push(4);
console.log(numbers, numbersCopy);
// [1, 2, 3] and [1, 2, 3, 4]
// numbers is left alone
This is not fine
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
Same as for
—impure, imperative, blah, blah, blah…it works! ?
numbers = [1, 2, 3];
numbersCopy = [];
i = -1;
while (++i < numbers.length) {
numbersCopy[i] = numbers[i];
}
Note: This also assigns objects/arrays by reference instead of by value.
This is fine
numbersCopy.push(4);
console.log(numbers, numbersCopy);
// [1, 2, 3] and [1, 2, 3, 4]
// numbers is left alone
This is not fine
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
Back in modern territory, we’ll find the map
function. Rooted in mathematics, map
is the concept of transforming a set into another type of set, while preserving structure.
In English, that means Array.map
returns an array of the same length every single time.
To double a list of numbers, use map
with a double
function.
numbers = [1, 2, 3];
double = (x) => x * 2;
numbers.map(double);
True, this article’s about cloning arrays. To duplicate an array, just return the element in your map
call.
numbers = [1, 2, 3];
numbersCopy = numbers.map((x) => x);
If you’d like to be a bit more mathematical, (x) => x
is called identity. It returns whatever parameter it’s been given.
map(identity)
clones a list.
identity = (x) => x;
numbers.map(identity);
// [1, 2, 3]
Note: This also assigns objects/arrays by reference instead of by value.
This function returns an array, just like map
, but it’s not guaranteed to be the same length.
What if you’re filtering for even numbers?
[1, 2, 3].filter((x) => x % 2 === 0);
// [2]
The input array length was 3, but the resulting length is 1.
If your filter
’s predicate always returns true
, however, you get a duplicate!
numbers = [1, 2, 3];
numbersCopy = numbers.filter(() => true);
Every element passes the test, so it gets returned.
Note: This also assigns objects/arrays by reference instead of by value.
I almost feel bad using reduce
to clone an array, because it’s so much more powerful than that. But here we go…
numbers = [1, 2, 3];
numbersCopy = numbers.reduce((newArray, element) => {
newArray.push(element);
return newArray;
}, []);
reduce
transforms an initial value as it loops through a list.
Here the initial value is an empty array, and we’re filling it with each element as we go. That array must be returned from the function to be used in the next iteration.
Note: This also assigns objects/arrays by reference instead of by value.
slice
returns a shallow copy of an array based on the provided start/end index you provide.
If we want the first 3 elements:
[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.
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 one safely 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!
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.
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.
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.
Originally published by Yazeed Bzadough at https://www.freecodecamp.org
#javascript #array #es6 #webdev