【JS】オブジェクトの代入の見方（分割代入）。const { } = obj

JSでオブジェクトの代入の記述が迷ったので確認内容のメモ。下記のような記述がどんな処理をしているかについて。

正式名称は分割代入。[(MDN 分割代入 公式ページ）](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)


<br>
##処理内容

パッと見、`const {} = obj`といった形になっているものが該当する。

パターンはいくつかあるが、複数のプロパティが入った要素に対して、一つのプロパティと変数が指定されている場合のみを考えてみる。


```:
const {プロパティ名: 変数} = オブジェクト
```

- **変数のみが新たに定義した値**
- プロパティ名は、オブジェクト内のプロパティと対応する

つまり、**指定したプロパティ名の値を任意の変数に格納**する処理となる。


<br>
##実例で確認

```js:例
objs = [{a:100, b:200}, {a:300, b:400}]

objs.map((obj) => {
    const {a: x} = obj
    console.log(x)
})

//結果
100
300
```

上記の場合、
`const {a: x} = obj`の1ループ目の処理は、
`const {a: x} = {a:100, b:200}`となる。

この式では**bは無視**で、a:100の100をxに代入した処理となる。

よって、`console.log(x)`で出力されるのは、プロパティaの値、100, 300のみとなる。



<br>
##応用編
上記の例で、オブジェクトobjsのプロパティaにのみ加算処理を行う方法。

```js:
objs = [{a:100, b:200}, {a:300, b:400}]

objs = objs.map((obj) => {
    const {a: x} = obj
    return {
        ...obj,
        a: x+1
    }
})

//出力
[{a:101, b:200}, {a:301, b:400}]
```

ポイントはスプレッド構文でobjを展開していること。
`...obj`なしの場合、aに足す１した結果のみが出力される。


<br>

```js:スプレッド構文なし
objs = [{a:100, b:200}, {a:300, b:400}]

objs = objs.map((obj) => {
    let {a: x} = obj
    return {
        a: x+1
    }
})

//出力
[{a:101}, {a:301}]
```


<br>
##分割代入
オブジェクトの値を取り出して変数に代入する処理を分割代入という。　`const {} = obj`の総称。

`const {プロパティ名: 変数} = オブジェクト`は一例であり、他にも指定方法がある。


<br>
##複数のプロパティを代入する方法
シンプルに、プロパティ名と変数を書き足していく。

`const {プロパティ名: 変数, プロパティ名: 変数,,,} = オブジェクト`

```js:複数のプロパティの値を代入
objs = [{a:100, b:200}, {a:300, b:400}]

objs.map((obj) => {
    const {a: x, b: y} = obj
    console.log(x, y)
})

//出力
100 200
300 400
```

同不順なので、プロパティaとbを入れ替えることも可能。

```js:複数のプロパティの値を代入(例２)
objs = [{a:100, b:200}, {a:300, b:400}]

objs.map((obj) => {
    const {b: x, a: y} = obj
    console.log(x, y)
})

//出力
200 100
400 300
```



<br>
##値を格納する変数を省略
プロパティ名をそのまま変数にすることもできる。

```js:プロパティ名を変数にする
objs = [{a:100, b:200}, {a:300, b:400}]

objs.map((obj) => {
    const {a, b} = obj
    console.log(a, b)
})

//出力
100 200
300 400
```


<br>
プロパティ名は元々定義してあるものを使う必要がある。元のプロパティ名と対応しない場合はundefinedになる。

```js:NG例
objs = [{a:100, b:200}, {a:300, b:400}]

objs.map((obj) => {
    const {x, y} = obj
    console.log(x, y)
})

//出力
undefined undefined
undefined undefined
```

objsの中に、xやyというプロパティはないので出力はundefinedになる。


<br>
##残り全部を代入
`...`を使うことで残り全部を指定することができる。

```js:
arr = [1,2,3,4,5]

let [a,b,...c] = arr

console.log(a) //1
console.log(b) //2
console.log(c) //[3,4,5]
```

上記のように、`[a,b,...c]`の場合、前方から一つづず、a=1, b=2, と当てはめていき、残りを...cに代入する。


<br>
###注意点
`...`がない場合は、単純に一つの値を代入するだけになる。

```js:
arr = [1,2,3,4,5]

let [a,b,c] = arr

console.log(a) //1
console.log(b) //2
console.log(c) //3
```

３つめ以降の[4,5]はどこにも代入されない。


<br>
また、`...`は最後にしか持ってこれない。
前方や途中の要素に`...`をつけるとエラーになる。

```js:
arr = [1,2,3,4,5]

let [a,...b,c] = arr

//エラー
Uncaught SyntaxError: Rest element must be last element
```


<br>
##objectを代入する場合

`const {a, b, c} = {e:1, d:2, c:3, b:4, a:5}`
といったパターンもある。

この場合、変数a,b,cにはそれぞれ、右側で該当している値が入る。

```js:
const {a,b,c} = {e:1, d:2, c:3, b:4, a:5}

console.log(a) //5
console.log(b) //4
console.log(c) //3
console.log(d) //Uncaught ReferenceError: d is not defined
```

変数として定義したa,b,cは呼び出せるが、dは変数として定義していないためエラーとなる。