JavaScriptオブジェクトで識別子として不正な名前のプロパティにアクセスする方法

**ブラケット記法を使わない縛りです笑**

*かなりどうでもいい内容ですので、あらかじめご了承ください。

JavaScript初学者の方にはもしかしたら学習の助けになる情報も含まれていないこともないかもしれないと思い、書いてみようと思います。(自分もまだまだ勉強中です)

まずは以下のコードをご覧ください。

```javascript
const obj = {
  "ho-ge": "ほーげ"
}
```
突然ですがここで問題です！
#####Q. ``objオブジェクトのho-geプロパティの値をブラケット記法を使わずに出力してください。``
どうでしょう。意外と悩みませんか？

またまた突然ですが、**JavaScriptの識別子には英数字、$、_(アンダースコア)のみを含めることができ、数字からはじめてはいけない**という決まりがあります。
識別子とは、変数や関数やオブジェクトのプロパティにつける名前のことです。要は変数名や関数名のことです。

**オブジェクトのプロパティ名ももちろん識別子ですが、内部的には文字列(もしくはシンボル)です。**
文字列であればどのような値でも問題なく、識別子として有効である必要はありません。
プロパティ名は、識別子としては不正な値でも、クオートで囲んであげれば(文字列リテラルで書けば)どんな名前であってもエラーにはなりません。

```javascript:obj.js
const obj = {
  hoge: "ほげ", // 識別子として正しい名前なのでクオートで囲んでなくてもok
  "1hoge": "1ほげ", // 数字から始まっているがクオートで囲んでいるのでok
  "ho-ge": "ほーげ" // 識別子に含めることができない文字(-)が入っているがクオートで囲んでいるのでok
}
```

上記のコードは問題なく実行できます。
しかし、上記オブジェクトのプロパティにアクセスする時には注意が必要です。
以下のコードをご覧ください。

```javascript:obj.js
const obj = {
  hoge: "ほげ", // 識別子として正しい名前なのでクオートで囲んでなくてもok
  "1hoge": "1ほげ", // 数字から始まっているがクオートで囲んでいるのでok
  "ho-ge": "ほーげ" // 識別子に含めることができない文字(-)が入っているがクオートで囲んでいるのでok
}
console.log(obj.hoge) // => ほげ
console.log(obj.1hoge) // エラー
console.log(obj.ho-ge) // エラー
```

識別子としては不正な名前がつけられているプロパティに**ドット記法**でアクセスしようとするとエラーになります。
ドット記法とは、``obj.hoge``のように``オブジェクト名.プロパティ名``の形でプロパティにアクセスする書き方です。

さて、ここで登場するのが**ブラケット記法**です。
ブラケット記法は``obj['hoge']``のように``オブジェクト名['プロパティ名']``という形でプロパティにアクセスする書き方です。
ブラケット記法を使えば、識別子としては不正なプロパティの値にもアクセスすることができます。

```javascript
const obj = {
  hoge: "ほげ",
  "1hoge": "1ほげ",
  "ho-ge": "ほーげ"
}
console.log(obj["1hoge"]) // => 1ほげ
console.log(obj["ho-ge"]) // => ほーげ
```

ここでもう一度問題をみてみましょう。

#####Q. ``objオブジェクトのho-geプロパティの値をブラケット記法を使わずに出力してください。``

そうなんです。今回はブラケット記法を使ってはいけないのです。(じゃあなんで説明した？)

さて、それでは早速答えです。笑
実際のところ色々とやり方はあるのだと思いますが、
私の答えは以下です。

```javascript:answer.js
const obj = {
  "ho-ge": "ほーげ"
}
const {"ho-ge": hoge} = obj // オブジェクトの分割代入
console.log(hoge) // => ほーげ
```
コード中にブラケット([])は存在していませんよね。

分割代入(Destructuring assignment)は、ES6から導入された文法で、代入式の一種です。
配列の分割代入とオブジェクトの分割代入の２種類があり、今回はオブジェクトの分割代入を利用しています。

↓オブジェクトの分割代入を利用したコード例です。

```javascript:destructuring.js
// movieオブジェクトを定義
const movie = {
  title: "ミッドサマー",
  director: "アリ・アスター",
  released: {
    jpn: "2020-02-21",
    usa: "2019-06-24",
  }
}

// 分割代入式を使ってmovieオブジェクトのtitle, director, jpn, usaプロパティを
// それぞれのプロパティ名と同名の変数に宣言代入
const {title, director, released: {jpn, usa}} = movie

console.log(title, director, jpn, usa)
// => ミッドサマー アリ・アスター 2020-02-21 2019-06-24
// ちなみにこの場合released変数は定義されないので注意
```
オブジェクトの宣言代入を使うと、一文でオブジェクトの任意の複数のプロパティを変数に一発で代入できるのです。
便利ですよね。

・左辺：{}の中に代入元となるオブジェクトのプロパティ名と同じ名前の変数をカンマ区切りで列挙する。
・右辺：代入元となるオブジェクト
プロパティの値がオブジェクトで、そのオブジェクトのプロパティも分割代入したい場合はコード例のように``{released: {jpn, usa}} ``とします。

JavaScriptのオブジェクトのプロパティは基本的には列挙順が保証されないので、分割代入する際はプロパティ名と同じ名前で変数を宣言する必要があります。
例えば、titleプロパティをmovieName変数に代入したいと思って以下のようにすると、

```javascript
const {movieName, director, released: {jpn, usa}} = movie
console.log(movieName, director, jpn, usa)
// => undefined アリ・アスター 2020-02-21 2019-06-24
```
のようにmovieName変数はundefinedになります。

でも変えたいですよね、変数名。
その場合は``{プロパティ名: 変数名}``とすればいけます。

```javascript:destructuring.js
const movie = {
  title: "ミッドサマー",
  director: "アリ・アスター",
  released: {
    jpn: "2020-02-21",
    usa: "2019-06-24",
  }
}

// titleプロパティをmovieName変数に、released.jpnプロパティをreleasedJpn変数に、released.usaプロパティをreleasedUsa変数に代入
// 入れ子になっているオブジェクトのプロパティにアクセスするためのコロンと、別名の変数に代入するためのコロンの役割の違いに注意
const {title: movieName, director, released: {jpn: releasedJpn, usa: releasedUsa}} = movie

console.log(movieName, director, releasedJpn, releasedUsa)
// => ミッドサマー アリ・アスター 2020-02-21 2019-06-24
```

ここで、answer.jsをもう一度見てみます。

```javascript:answer.js
const obj = {
  "ho-ge": "ほーげ"
}
const {"ho-ge": hoge} = obj // オブジェクトの分割代入
console.log(hoge) // => ほーげ
```

最初の方に書いたように、オブジェクトのプロパティ名は文字列です。
answer.jsでは分割代入を使って、識別子としては不正な名前のプロパティを識別子として有効な変数に代入して出力しているということです。

いろいろと脱線して長くなってしまいましたが以上になります。
分割代入他にも様々な仕様があって面白ですよ。
あと、ミッドサマー面白いですよ。