JS spread operator (...)
Tags: javascript, spreadoperator
Published: 2021-06-04 15:41:17

## Definition

JavaScript ES6 introduced the spread operator and it only worked for arrays. ES2018 expands the spread operator (...) to make it works with own enumerable properties of an object. 

Spread syntax (...) allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected. 

reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

I feel like this definition is hard to understand. So let me put in other words, **the spread operator takes an iterable such as array and expands it into elements.**

## Examples
### Array
#### 1. Merge Arrays
**Without spread operator, using Array.prototype.concat(),**
```
let array1 = [1, 2, 3];
let array2 = [4, 5, 6];

let newArray=array1.concat(array2);
newArray; //-> [1, 2, 3, 4, 5, 6]
```

**With spread operator,**
```
let array1 = [1, 2, 3];
let array2 = [4, 5, 6];

let mergeArray = [...array1, ...array2];
mergedArray; //-> [1, 2, 3, 4, 5, 6]
```
#### 2. Clone Array
In JavaScript, arrays are reference types("pass by reference", it just copies address of that array), so you can't just create a new copy of an array using =. When you are change the new array or original array, it will also change the other another like example below:
```
let original = [1, 2, 3];
let newArray = original;

newArray[0]=5;
newArray; //-> [5, 2, 3]
original; //-> [5, 2, 3]
```
Oh no, both of them changed. Let's try again with spread operator.
```
let original = [1, 2, 3];
let newArray = [...original];

newArray[0]=5;
newArray; //-> [5, 2, 3]
original; //-> [1, 2, 3]
```
Now, original array didn't affect when we changed the newArray,  only newArray was modified.
#### 3. String to Array
Using spread operator to a string, it will return an array of individual substrings (split into characters).
```
let st = 'hello';
let array = [...st];
array; //-> ['h', 'e', 'l', 'l', 'o']
```
#### 4. Math
The Math object in javascript, the array won't work but with spread operator it will work 
```
let array = [1,2,3,10];
console.log(Math.max(array)); //->NaN
console.log(Math.max(...array)); //->10
```
reference:
https://www.samanthaming.com/tidbits/92-6-use-cases-of-spread-with-array/
https://www.geeksforgeeks.org/javascript-spread-operator/

### Object
The spread operator (…) with objects is used to create copies of existing objects with new or updated values or to make a copy of an object with more properties.

let's say we have 3 objects,
```
let user1 = {
    name: 'jean',
    age: 30
};
let user2 = {
    name: 'John',
    age: 20
};
let jean = {
    location: 'NY',
    hobby: 'coding'
};
``` 
#### 1. Clone Object
**Using Object.assign()**
```
let clonedUser = Object.assign({}, user1);
clonedUser; //-> {name: 'jean', age: 30 }
```

**Using Spread Operator**
```
let clonedUser = { ...user1 };
clonedUser; //-> {name: 'jean', age: 30 }
```
Both of them works same way.
#### 2. Merge Objects (with different properties)
**Using Object.assign()**
1. This will modify the user1 too.
```
let MergedUser = Object.assign(user1, jean);
MergedUser; //-> {name: "jean", age: 30, location: "NY", hobby: "coding"}
user1; //-> {name: "jean", age: 30, location: "NY", hobby: "coding"}
```
2. Making new Merged obj, won't modify the user1
```
let MergedUser = Object.assign({}, user1, jean);
MergedUser; //-> {name: "jean", age: 30, location: "NY", hobby: "coding"}
user1; //-> {name: 'jean', age: 30 }
```
Without using {} empty object, it will modify the user1. Simply saying that first take the user1 and then add jean to the user1. If you don't want to mutate user1 then you must use empty obj. "let MergedUser = Object.assign({}, user1, jean);" this is saying that create the empty newobj and copy user1 to it and then add jean to that newobj. 

**Using Spread Operator**
```
let MergedUser = { ...user1, ...jean};
MergedUser; //-> {name: "jean", age: 30, location: "NY", hobby: "coding"}
```
#### 3. Merge Objects (with same properties)
Using Object.assign
```
let MergedUser = Object.assign({}, user1, user2);
MergedUser; //-> {name: "John", age: 30}
```
Using Spread Operator
```
let MergedUser = { ...user1, ...user2};
MergedUser; //-> {name: "John", age: 30}
```
The properties are overwritten by other objects that have the same properties later in the parameters order.
This overwriting will come in handy when you pass objects to other functions that update state.
#### Bonus Update property
```
const obj = { hi: "x", hello: "y" };
const updatedObj = { ...obj, hi: "z" };
updatedObj; //-> {hi: z, hello: "b"}
```
This is what I talked earlier when explaining with using Object.assign() with empty obj or not. So in this case, we update obj with new value.

#### Bonus Create new obj with Updated property of other obj
```
//using Object.assign()
let user = {id: 1, name: 'jean', age: 30};
let YoungerUser = Object.assign({}, user, {age: user.age - 1})
//using spread operator
let user = {id: 1, name: 'jean', age: 30};
let YoungerUser = {...user, age: user.age - 1}
```  
It's creating new obj, "YoungerUser". Start with a new empty object, copy over everything from the original user, then overwrite the age property with a new value.
reference: 
https://www.rockyourcode.com/use-the-spread-operator-to-update-objects/