JS Spread syntax ...
Spread syntax (...)
As function argument:
myFn (arg1, arg2, ...arg3, arg4) // arg3 is an iterable object (arrays, strings)
let arr9 = [1, 3, 5]
function sum(n1, n2, n3) {
return n1 + n2 + n3
}
sum(...arr9) // 9
sum.apply(null, arr9) // 9
*Be ware of the risk of exceeding the JavaScript engine's argument length limit!
Maybe it's just me but it suddenly(finally?) made sense to me why Math.max(arrOfNumbers) doesn't work but Math.max(...arrOfNumbers) does:
let numArr = [3, 5, 7, 19]
console.log(Math.max(numArr)) // NaN
console.log(Math.max(...numArr)) // 19
let numArr2 = [70, 100]
console.log(Math.max(...numArr, ...numArr2)) // 100
Array literals:
[item1, item2, ...item3, item4] // item3 is an iterable object (arrays, strings)
let shortArr = [4, 5, 6]
let longArr = [1, 2, 3, ...shortArr, 7, 8]
console.log(longArr) // [1, 2, 3, 4, 5, 6, 7, 8]
Object literals:
{key: value, ...obj, key: value, key: value}
let arr = [1, 3, 5, 7]
let obj1 = {...arr}
let obj2 = {'x':1, ...arr, 'z':100}
let obj3 = {'c': 9, ...obj1, 'a': 8, 'b': 106}
console.log(obj1) // {0: 1, 1: 3, 2: 5, 3: 7}
console.log(obj2) // {0: 1, 1: 3, 2: 5, 3: 7, x: 1, z: 100}
console.log(obj3) // {0: 1, 1: 3, 2: 5, 3: 7, c: 9, a: 8, b: 106}
*Note that the key:value pairs got "reordered"--the iterable key:value pairs were placed before all other pairs.
String
let str = 'abc'
console.log(...str) // a b c
let arr = [...str]
console.log(arr) // ['a', 'b', 'c']
*Although, I don't find the spread syntax particularly useful to strings (yet).
Superpower of the spread syntax
Works with 'new' operator when calling a constructor
const dateFields = [2022, 0, 1]; // [year, month, date]
const d = new Date(...dateFields);
console.log(d) // Sat Jan 01 2022 00:00:00 GMT-0800 (Pacific Standard Time)
*Can't use apply() to construct a function
Create a copy of an array
let arr = [2, 4, 5, 0]
let copyOfArr = [...arr] // another way of creating a copy is arr.slice()
copyOfArr.sort((a, b) => a - b)
console.log(arr) // [2, 4, 5, 0]
console.log(copyOfArr) // [0, 2, 4, 5]
Create new array using an existing array or concatenating arrays
let arr1 = [2, 3]
let arr2 = [1, ...arr1, 4]
console.log(arr2) // [1, 2, 3, 4]
let arr3 = [5, 6]
let arr4 = [...arr2, ...arr3]
console.log(arr5) // [1, 2, 3, 4, 5, 6]
Create an array filled with integers
let nums = [...Array(10).keys()] // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Clone or merge objects
const obj1 = { z: 'bar', x: 42 }
const obj2 = { z: 'baz', y: 13 }
const clonedObj = { ...obj1 }
console.log(clonedObj) // {z: 'bar', x: 42}
const mergedObj = { ...obj1, ...obj2 }
console.log(mergedObj) // {z: 'baz', x: 42, y: 13}
*Note that spread syntax doesn't mutate an object (need to use Object.assign(obj, {key: newValue}):
const obj1 = { z: 'bar', x: 42 }
Object.assign(obj1, { x: 1337 })
console.log(obj1); // Object { z: "bar", x: 1337 }
const obj1 = { z: 'bar', x: 42 }
const obj2 = { z: 'baz', y: 13 }
const merge = (...objects) => ({ ...objects })
const mergedObj = merge(obj1, obj2)
console.log(mergedObj) // { 0: { z: 'bar', x: 42 }, 1: { z: 'baz', y: 13 } }
*As shown above, the spread syntax spreads an array of arguments into the object literal. To do a "real" merge, rewrite the merge function using reduce():
const obj1 = { z: 'bar', x: 42 }
const obj2 = { z: 'baz', y: 13 }
const mergeObjects = (...objects) => objects.reduce((acc, cur) => ({ ...acc, ...cur })) // note here objects are an array
const mergedObject = mergeObjects(obj1, obj2)
console.log(mergedObject) // { z: 'baz', x: 42, y: 13 }
Personally, I found the function expression above confusing, so I rewrote the function below with commented out console.logs that helped me understand the code:
let obj1 = {a: 2, b: 5, c: 7}
let obj2 = {a: 2, d: 4}
function mergeFn(...objects) {
// console.log(...objects)
return objects.reduce((acc, cur) => {
// console.log(acc)
// console.log(cur)
// console.log({...acc, ...cur})
return {...acc, ...cur}
}, {})
}
let result = mergeFn(obj1, obj2)
console.log(result) // {a: 2, b: 5, c: 7, d: 4}
Well, that's all for now. With great power comes great responsibility risk, but I can't wait to try using the spread syntax more when solving coding challenges, even if that means more bugs and errors.