The three dots in javascript - spread operator


The JavaScript spread operator or the three dots operator allow to copy an array part or full array or object into another array or object, it helps ease the problem of looping over an array and push elements.
We can concatenate arrays easily with the spread operator and without altering the initial array; in the example below with simple syntax both arrays are concatenated. To get the same results without spread operator, we need to loop over the second array and push every element.
Concatenate arrays with spread operator vs loop and push
const a = [1, 2];
const b = [3, 4, 5];
//the concatenated array using spread operator
const c = [...a, ...b];
console.log("Array c is : ");
console.log(c);
//Array c is:
//[ 1, 2, 3, 4, 5 ]
//loop over array b and push its elements to array a
b.forEach((x) => a.push(x));
console.log("Array a was altered, new values are : ");
console.log(a);
//Array a was altered, new values are:
//[ 1, 2, 3, 4, 5 ]
The spread operator can be used also in function calls, we can simply pass a spread array to a function and it matches the function arguments, in the sample below we test with two different arrays, one matching exactly the function arguments number, and the second array has one more argument.
Even if the array has more elements than what the function need, it is still working and using only the first two arguments.
const f = (x, y) => x * y;
const tableau = [2, 3];
const nouveauTableau = [3, 4, 5];
console.log("Product : " + f(...tableau));
//Product : 6
console.log("Product : " + f(...nouveauTableau));
//The function takes only the first two arguments and ignores the rest
//Product : 12
Push elements with spread operator
It is possible to use the spread operator to push elements on array like the below, but keep in mind that it does not alter the array as the push method would do. For our example, we spread the first array and then we concatenate it with element b, the results are assigned to another constant. While we push directly the element with push in the second method and the array is changed after then.
const a = [1, 2];
const b = 3;
const c = [...a, b];
//push is altering the array a
const d = a.push(b);
//array c and a are similar now
console.log(c);
//we print array a as it has been altered by push method
console.log(a);
Rest parameters
Rest parameters are the opposite of what a spread operator would do; it would gather the rest of parameters in one variable with ease. Let’s take a look to this example to learn more:
//First example with rest parameters and objects
const { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(z);
//{ a: 3, b: 4 }
//Second example with simple array
const numbers = [1, 2, 3, 4, 5, 6];
const [one, two, ...rest] = numbers;
console.log(one);
//1
console.log(two);
//2
console.log(rest);
//[ 3, 4, 5, 6 ]
For the first assignment, an object containing objects, we extract the first two objects and assign them to x and y respectively, and the rest, where the name came from is assigned to z, for the second example we get the rest of the array without the first two elements.
Array.prototype.slice or slice vs Rest parameters
It is possible to mimic the Rest parameters with slice method and it does not alter the array state as well.
array = ["cat", "mouse", "toad", "tiger", "elephant"];
const [x, ...y] = array;
console.log(y);
//rest takes out the first parameter and copy the rest into y
//[ 'mouse', 'toad', 'tiger', 'elephant' ]
console.log("array after slice: ");
console.log(array.slice(1));
//Slice perform the same
//[ 'mouse', 'toad', 'tiger', 'elephant' ]
We have sliced the first element, so we can assign the rest to a variable and work with it, or work simple with Rest parameters and perform the same; it is question of choice in that case.
Spread properties
Spread properties is the fact that you can overwrite an object value if the objects have the same keys,
const data1 = { name: "ali", age: 31 };
const data2 = { name: "ben", gender: "male" };
const newObj = { ...data1, ...data2 };
console.log(newObj);
//{ name: 'ben', age: 31, gender: 'male' }
So the value of name is ben, which is the last value assigned and the rest still the same as object keys are different.
Spread arrays into objects
When working with spread operator, make sure you spread to another array; spread into an object might give new format like the one below
const a = ["x", "y"];
const b = ["d", "e", "f"];
const c = { ...a, ...b };
console.log(c);
//object with index as a key and value
//{ '0': 'd', '1': 'e', '2': 'f' }
The object is spreading the two arrays values, with array index as a key.
Spread works only with iterable objects
The spread operator works only with iterables, that means it cannot loop over an object unless it is contained on an array. The sample below is not working as our obj is not contained in an array and Node.js throws an error.
const obj = { mykey: "somevalue" };
const array = [...obj]; // TypeError: obj is not iterable
Now keep the same object but wrap it this time in an array and print out the value
const obj = { mykey: "somevalue" };
const newObj = [obj];
console.log([...newObj]);
//[ { mykey: 'somevalue' } ]
This prints out the array value as expected.