Top Fascinating Uses of the Spread Operator

The Spread Operator

ES2016 brings us many many goodies, one of which I came across a couple of days ago is the Spread Operator. I have become a big fan of it, not just because of its utility but also as it helps me to shorten my code. So what is it exactly?

Spread Operator
Simply put, the spread operator allows an expression(that could be an array/object) to be expanded in places where multiple elements/variables/arguments are expected.

Syntax: ...

This will be best clarified by the following use-cases:

1. Merge Arrays/Objects

Lets assume we wish to insert an array, named center in between another array, List:

var list =[1, 2, 3, 9, 12]; 
var center = [7 , 8]; 
// with spread operator
var result1 = [1, 2, 3, ...center, 9, 12]; // [1,2,3,7,8,9,12] 
// without spread operator
var result2 = [1, 2, 3, center, 9,12];     // [1,2,3, [7,8], 9, 12]

As you can see above, the Spread operator inserts the individual elements similar to Array.splice() instead of inserting the array as a whole.

// For Objects
const obj1 = { c: 3, d: 4 };
const obj2 = { a: 1, b: 2, ...obj1 };      // { a: 1, b: 2, c: 3, d: 4 }

// When duplicate properties clash, the order of '...' determines the outcome.
// The property put in last, wins!
// when spread operator is last
const obj2 = { b: 'x', c: 'y', ...obj1};   // {b: 'x', c: 3, d: 4 }
// spread operator is first
const obj2 = { ...obj1, b: 'x', c: 'y' };  // { b: 'x', c: 'y', d: 4 }

2. Call Functions with Arguments

function sum (x,y,z) {
    return x + y + z;
}
var args = [5,7,5];
sum(...args);

As you can see the spread operator expands the arguments passed to the function sum();
Until now, to do the same thing we had to use Function.prototype.call() or Function.prototype.apply() by passing a useless null parameter like

sum.apply(null, args); or sum.call(null, args);

Similarly, JS functions like Math.max(...args); can be called directly by passing an array instead of using call()/apply()

3. Eliminate duplicates from an Array:

const arr = [8, 5, 3, 5, 8, 3, 5];
const items = [...new Set(arr)];
console.log(items); // [ 8, 5, 3 ]

4. String to Character Array

The spread operator can be easily used to convert strings into character arrays.

const str = "hello";
const chars = [...str];
console.log(chars); // ['h', 'e',' l',' l', 'o']

5. Copying / Concatenating Arrays/Objects:

Traditionally to concatenate arrays, we used Array.prototype.concat() as follows:

var arr1 = ['a', 'b', 'c'];
var arr2 = ['d', 'e', 'f'];
arr = arr1.concat(arr2);   // ['a', 'b', 'c', 'd', 'e', 'f']

The spread operator makes this as simple as

// For Arrays
arr = [...arr1, ...arr2];
console.log(arr); // ['a', 'b', 'c', 'd', 'e', 'f']

// For Objects
const obj1 = { a: 11, b: 22 };
const obj2 = { c: 33, d: 44 };
const merged = { ...obj1, ...obj2 }; // { a: 11, b: 22, c: 33, d: 44 }

To copy an Array/Object

The spread operator can be used to create a shallow copy of another array/object as follows

// For Arrays
var arr1 = ['a', 'b', 'c'];
var arr2 = [...arr1];
console.log(arr2);            // ['a', 'b', 'c']

// For Objects
const obj1 = { a: 11, b: 22 };
const obj2 = { ...obj1 };     // creates a shallow copy
console.log(obj2);            // { a: 11, b: 22 }

Creating a shallow copy implies that changing original array(arr1) will have no effect on the copied array (arr2). This is because the value of arr1 is expanded to fill the brackets of our arr2 array definition. Thus, we are setting arr2 to equal the values of arr1 not to arr1 itself.
To clarify, if you copy the array by setting the value as var arr2 = arr1;, any changes to arr1 will be reflected in arr2.

6. Destructuring / Rest Syntax:

The Rest Parameters looks exactly like the spread operator and is actually used for destructuring

// For Arrays
var [a, ...b] = [1, 2, 3];
console.log(a); // 1
console.log(b); // [2, 3]

// For Objects
let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}
console.log(a);    // 10 
console.log(b);    // 20 
console.log(rest); // { c: 30, d: 40 }

As seen above, you can extract the information into variables. The remaining unassigned properties are added on to the variable with the spread operator.

7. Conditional Arguments:

The spread operator can be used to pass in conditional function parameters as follows:

let condition = true;
Math.max(...condition ? [10,20,30] : [])  // 30
// The above code is similar:
if (condition) Math.max([10,20,30])       // 30
else Math.max();                          // -Infinity

Caveats:

As far as performance is concerned, there are a few cases where the spread operator falls short. For example, check out this jsperf to compare array concatenation.

Note that the ... operator used with Arrays is a part of ES6. But using it with Objects is a stage-3 addition. And although transpilers like babel, typescript support it, it is not the standard as yet.

 

All modern browsers support the new ES6 syntax so if you haven’t taken the time to play around, you definitely should. The Spread operator is a useful addition that one must be aware of!

Leave a Reply