Love knows no distance, boundaries, or conditions it can be spread beyond our imagination. The JavaScript spread operator is there to spread this love among developers. Along with catchy syntax, it has lots of benefits that our brain needs to comprehend. In this article, we will try to explore as many features as possible of the spread operator.
Spread love as thick as you would Nutella! Some delicious spreads are cheese, jam, butter, Nutella, or JavaScript's spread operator. Just like its brother (Rest Parameter) it is introduced in ES6 (2015) as a feature to resolve the array and object's cloning, inserting, and merging problems. Let us put some smiles on our faces and understand the power of the three dots, their conditions, and scenarios.
We will check the Spread Operator with following programming constructs:
They can be used to spread an array to a function's parameter list.
// passing array as function parameter
function add(num1, num2, num3) {
return num1 + num2 + num3
}
const arr = [10, 20, 30]
const sum = add(...arr)
console.log(sum)
// 60
Here, instead of sending parameters using the array index individually, we can simply put three dots before the array name in the function's argument list at the time of calling; and that's it! we are now supplying three arguments to the add function namely 10, 20, and 30.
Likewise, they can also jam with Math functions in a similar manner.
// passing array as function parameter
const arr = [10, 20, 30]
// without spread
// const min = Math.min.apply(null, arr)
// const max = Math.max.apply(null, arr)
const min = Math.min(...arr)
const max = Math.max(...arr)
console.log(min, max)
// 10 30
Here, instead of using the apply method to supply array values as parameters to a function; we can simply use the spread operator for the Math's min and max functions.
Spread operator can be used with an array for a number of operations such as concatenating, inserting, and cloning.
We can use the spread operator to concatenate arrays as shown below:
// concat arrays
const arr1 = [10, 20]
const arr2 = [30, 40]
const arr3 = [...arr1, ...arr2]
console.log(arr3)
// [ 10, 20, 30, 40 ]
// other
const arr4 = arr1.concat(arr2)
console.log(arr4)
// [ 10, 20, 30, 40 ]
Here, arr1 and arr2 are concatinated to form arr3. So no need to call the concat function anymore like we are doing with arr4.
We can use the spread operator to insert array values to specific location of another array as shown below:
// inserting into arrays
const arr1 = [20, 30]
const arr2 = [10, ...arr1, 40, 50]
console.log(arr2)
// [ 10, 20, 30, 40, 50 ]
Here, we are using the spread operator to insert the values of arr1 into arr2 1st index position. Note that we are doing this at the time of arr2 creation.
Cloning arrays now become easy peasy with spread; instead of pointing to the same reference, they will create a new reference.
Below shows what happens if we use the assignment operator directly with arrays:
// cloning arrays
// not cloned
const arr1 = [10, 20]
const arr2 = arr1
console.log(arr1 === arr2)
// arr1 === arr2 -> true (same reference)
Here, we are getting true because both arr1 and arr2 points to same reference where the actual array data is present in the memeory.
We can use spread operator to clone an array with a new reference:
// cloning arrays
const arr1 = [10, 20]
const arr2 = [...arr1]
console.log(arr1 === arr2)
// arr1 === arr2 -> false (new reference)
Here, we are cloning arr1 to arr2 and checking the refernces are same or not; and we are getting false we have used spread operator for arr2.
Check out the other ways (without using spread operator) to solve the cloning problem:
// cloning arrays
const arr1 = [10, 20]
const arr2 = arr1.concat()
const arr3 = arr1.slice(0)
const arr4 = arr1.map(i => i)
const arr5 = arr1.filter(i => true)
const arr6 = Array.from(arr1)
const arr7 = JSON.parse(JSON.stringify(arr1))
console.log(arr1 === arr2)
console.log(arr1 === arr3)
console.log(arr1 === arr4)
console.log(arr1 === arr5)
console.log(arr1 === arr6)
console.log(arr1 === arr7)
// arr1 === arr2 -> false (new reference)
// arr1 === arr3 -> false (new reference)
// arr1 === arr4 -> false (new reference)
// arr1 === arr5 -> false (new reference)
// arr1 === arr6 -> false (new reference)
// arr1 === arr7 -> false (new reference)
Here, we can clearly see that spread operator provide a clean and easy way to clone as compare to the other approaches shown above.
Spread operator can be used with an array for a number of operations such as merge, merge with overriding, property merging, and cloning.
Spread understands JavaScript's object, they can be used to merge objects as shown below:
// merge object
const obj1 = { id: 1001, name: 'John' }
const obj2 = { job: 'Clerk', salary: 2000 }
const obj3 = { ...obj1, ...obj2 }
console.log('obj1:', obj1)
console.log('obj2:', obj2)
console.log('obj3:', obj3)
// { id: 1001, name: 'John' }
// { job: 'Clerk', salary: 2000 }
// { id: 1001, name: 'John', job: 'Clerk', salary: 2000 }
Here, obj1 and obj2 are merged and form a new object called obj3 that contains properties of both the objects (obj1 and obj2).
Along with merge, objects can override another object at the time of merge, it follows the left to right overriding as shown below:
// merge object (override)
const obj1 = { id: 2001, name: 'Martin' }
const obj2 = { name: 'Allen', job: 'Sales' }
const obj3 = { ...obj1, ...obj2 }
console.log('obj1:', obj1)
console.log('obj2:', obj2)
console.log('obj3:', obj3)
// obj1: { id: 2001, name: 'Martin' }
// obj2: { name: 'Allen', job: 'Sales' }
// obj3: { id: 2001, name: 'Allen', job: 'Sales' }
Here, everything seems same as before but the obj2 overrides the properties of obj1. As you can see for obj3 the name becomes Allen. So if properties are same accross merging objects then the objects those are on the right side will get precedence over the left ones.
If we want to add properties to an object on fly, then we can use the spread operator to that for us as shown below:
// adding new properties to object
const obj1 = { id: 2001, name: 'Martin' }
const obj2 = {
...obj1,
job: 'Sales',
salary: 2000
}
console.log('obj1:', obj1)
console.log('obj2:', obj2)
// obj1: { id: 2001, name: 'Martin' }
// obj2: { id: 2001, name: 'Martin', job: 'Sales', salary: 2000 }
Here, obj2 holds all of the obj1's properties along with new ones, the job and salary.
Below shows what happens if we use the assignment operator directly with objects for cloning:
// cloning objects
// not cloned
const obj1 = { id: 1001, name: 'John' }
const obj2 = obj1
console.log(obj1 === obj2)
// obj1 === obj2 -> true (same reference)
Here, we are getting true because both obj1 and obj2 points to same reference where the actual object data is present in the memeory.
Similar to array, object can also be cloned as shown below:
// cloning objects
const obj1 = { id: 1001, name: 'John' }
const obj2 = { ...obj1 }
console.log(obj1 === obj2)
// obj1 === obj2 -> false (new reference)
Here, we are cloning obj1 to obj2and checking the refernces are same or not; and we are getting false we have used spread operator for obj2.
Check out the other ways (without using spread operator) to solve the cloning problem:
// cloning objects
const obj1 = { id: 1001, name: 'John' }
const obj2 = Object.assign({}, obj1)
const obj3 = JSON.parse(JSON.stringify(obj1))
console.log(obj1 === obj2)
console.log(obj1 === obj3)
// obj1 === obj2 -> false (new reference)
// obj2 === obj3 -> false (new reference)
Here, we can clearly see that spread operator provide a clean and easy way to clone as compare to the other approaches shown above.
Last but not least, they can also make you picky by splitting your string into a character array.
// spread string
const str1 = 'Foo World'
const chars = [...str1]
console.log(chars)
// [
// 'F', 'o', 'o',
// ' ', 'W', 'o',
// 'r', 'l', 'd'
// ]
We all know that strings are basically collection of characters, spread can also help you to spread these characters apart.
December 31, 2020
October 19, 2020
March 02, 2022