【javascript】スプレット構文の使い方基礎

jsのスプレット構文うろ覚えすぎて一瞬なにそれ？となった（やばい）ので改めて調べて手を動かして覚えよう！ということでその備忘録です。
間違いや認識違いなどなにかあったらコメントいただけると嬉しいです〜

#スプレット構文とは

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax

MDN先生によると
>スプレッド構文 (...) を使うと、配列式や文字列などの反復可能オブジェクトを、0 個以上の引数 (関数呼び出しの場合) や要素 (配列リテラルの場合) を期待された場所で展開したり、オブジェクト式を、0 個以上のキーと値の組 (オブジェクトリテラルの場合) を期待された場所で展開したりすることができます。

そのまんまですね。要素を展開してくれるので、配列の[ ]やオブジェクトの{ }を外すことができるし、変更などで使う事もできる。

#使い方
##展開

シンプルな配列の場合`[]`をはずして展開されます。
`array`という箱から１つづつポイポイ出してくれた（展開した）ので`[]`がとれたということですね。

```.js
const array = [1,2,3]

console.log(array) //[ 1, 2, 3 ]
console.log(...array) //1 2 3
```
　

オブジェクトの場合は`{}`をつける必要があります。箱から１つづつポイポイ出しても`key`と`value`はあるからです。
オブジェクトのすべてのキーと値の組を渡してくれます。

```.js
const objectArray = {a: 1, b:2}

console.log(objectArray) //{ a: 1, b: 2 }
console.log({...objectArray}) //{ a: 1, b: 2 }
```
　
 
文字列を展開することもできます。

```.js 
const str = "こんにちは"
console.log(str)//こんにちは
console.log(...str)//こ ん に ち は
```

配列やオブジェクトに展開することもできます。

```.js
const strArray = [...str]
console.log(strArray) //[ 'こ', 'ん', 'に', 'ち', 'は' ]

const strObject = {...str}
console.log(strObject)//{ '0': 'こ', '1': 'ん', '2': 'に', '3': 'ち', '4': 'は' }
```


##追加（マージ）

配列同士をマージしたり、前後に要素を追加することができます。

```.js
const array1 = [1,2,3]
const array2 = [4,5,6]

const array3 = [...array1,...array2]
const array4 = [...array2,7,8,9]
const array5 = [-2,-1,0,...array1]

console.log(array3) //[ 1, 2, 3, 4, 5, 6 ]
console.log(array4) //[ 4, 5, 6, 7, 8, 9 ]
console.log(array5) //[ -2, -1, 0, 1, 2, 3 ]
```
　
 
オブジェクトも同様です

```.js
const objectArray1 = {a: 1, b:2}
const objectArray2 = {c: 3, d:4}

const objectArray3 = {...objectArray1,...objectArray2}
const objectArray4 = {...objectArray1, d: 4}
const objectArray5 = {z: 0, ...objectArray1}

console.log(objectArray3) //{ a: 1, b: 2, c: 3, d: 4 }
console.log(objectArray4) //{ a: 1, b: 2, d: 4 }
console.log(objectArray5) //{ z: 0, a: 1, b: 2 }
```
  
 
**キーの名前が同じ場合はマージされ、後の値で上書きされます**

```.js
const objectArray1 = {a: 1, b:2}
const objectArray2 = {c: 3, d:4}

const objectArray3 = {...objectArray1,...objectArray2, d: 10}
const objectArray4 = {d: 20, ...objectArray1}

console.log(objectArray3) //{{ a: 1, b: 2, c: 3, d: 10 }
console.log(objectArray4) //{ d: 20, a: 1, b: 2 }
```


##複製
変数を渡してあげることで、`arr.slice()` のような動きをしてくれるので、変数の参照渡しを回避することができます。

```.js
const arr1 = [1, 2, 3]
const arr2 = arr1
const arr3 = [...arr1]

arr1.push(4);

console.log(arr1)// [ 1, 2, 3, 4 ]
console.log(arr2)// [ 1, 2, 3, 4 ]
console.log(arr3)// [ 1, 2, 3 ]
```

オブジェクトの場合も同様です

```.js
const objectArray1 = {a: 1, b:2}
const objectArray2 = objectArray1
const objectArray3 = {...objectArray1}


objectArray1.c= 3;

console.log(objectArray1)// { a: 1, b: 2, c: 3 }
console.log(objectArray2)// { a: 1, b: 2, c: 3 }
console.log(objectArray3)// { a: 1, b: 2 }
```

###注意点
コピーは１段階の深さで行われるため、多次元配列のようなオブジェクトをコピーする場合には適していません。
次の例では、`array1`にも影響が出てしまっています。

```.js
let array1 = [[1], [2], [3]];
let array2 = [...array1];

array2.shift().shift();
console.log(array1)// [ [], [ 2 ], [ 3 ] ]
console.log(array2)// [ [ 2 ], [ 3 ] ]
```

#関数使用例

```.js
function sum(x, y, z) {
    return x + y + z
}

const numArray = [1,2,3]
console.log(sum(...numArray))// 6
```