オブジェクトリテラルのプロパティ/メソッドのいろんな書き方（ES6版）

*ECMAScript 6* がいよいよ[標準仕様](http://www.ecma-international.org/ecma-262/6.0/)となり、ブラウザでの実装もより一層進んできています。
オブジェクトリテラルの書き方ひとつ取っても、大変多彩になりました。

```js
var d = 42;
var obj = {
  a: 42,
  "b": 42,
  0: 42,
  ["c"] : 42,
  d,
  e(){},
  get f(){},
  set g(v){},
  *h(){}
};
```
これらを全て把握するだけでも一苦労です :dizzy: 
ここではそれぞれの書き方を、ひとつひとつざっくり見ていきたいと思います。

尚、ここで紹介するコードは、一部のブラウザでは動かないことがあります。
投稿時点で最新の GoogleChrome 44 であればすべて動作することを確認しましたので、よければそちらをお使いください。

#`var obj = { prop: value };`
一番慣れ親しんできた書き方だと思います。
しかしプロパティ名の付け方には、細かな決まりがあります。以下のコードで再確認してみてください。

```js
var obj = {
  prop: 42,
  prop123: 42,
/* 123prop: 42, */ // 数字から始まってはいけない
  \u0070: 42, // プロパティ名はエスケープが可能
/* \x70: 42, */ // ただし \xXX でのエスケープは不可
  if: 42, // 変数名とは違い、予約語も可能
  for: 42 // 〃
};
```

#`var obj = { "prop": value };`
あまり使う機会がない書き方かもしれません。*JSON*を使う人にはお馴染みでしょう。
`"prop"`の代わりに`'prop'`を使うことも可能です。空白文字を含めたり、空の文字列にすることもできます。

```js
var obj = {
  "prop": 42,
  'prop2': 42,
  "my prop": 42,
  "": 42
};
```

#`var obj = { 0: value };`
プロパティ名に数値リテラルを使った書き方です。
数値リテラルとは言うものの、プロパティ名は文字列に変換されるので注意が必要です。

```js
var obj = {
  0: "value",
  1e2: "value", // 指数表記が可能
  1e+3: "value", // 〃
  1e-3: "value", // 〃
  1.23: "value", // 小数表記が可能
  .456: "value", // 先頭の 0 を省略した小数表記が可能
  789.: "value", // 小数点以下を省略した小数表記が可能
  0xff: "value", // 16進数表記が可能
  0o77: "value", // 8進数表記が可能
  0b11: "value", // 2進数表記が可能
  0123: "value" // strict mode でなければ、0 で始まる8進表記も可能
};

for(var i in obj) console.log(i, typeof i); // 全て "string"
```

#`var obj = { ["pr" + "op"]: value };`
*ECMAScript 6* の目玉のひとつ、**Computed property names** です。
`[]`で囲った中身を計算して、結果をプロパティ名とします。
計算結果の型が *Symbol* のならそのまま、それ以外の場合は *String* に変換されます。

```js
var obj = {
  ["pr" + "op"] : 42, // "prop": 42, と等価
  [1 + 2]: 42, // "3": 42, と等価
  [!true]: 42, // "false": 42, と等価
  [{}]: 42, // "[object Object]": 42, と等価
  [function(){ return "foo"; }()]: 42, // "foo": 42, と等価
  [Symbol()]: 42 // 文字列の代わりに Symbol を指定できる
};
```

#`var obj = { prop };`
`: value`を省略した形になっています。
このプロパティの値は、その文脈における変数`prop`の値になります。
言い換えると、`var obj = { prop: prop };`の簡略的な書き方です。

```js
var prop = 0;
var obj = { prop }; // obj = { prop: 0 }; と等価
with( { prop: 1 } ){
  var anotherObj = { prop }; // anotherObj = { prop: 1 }; と等価
}
```


#`var obj = { method(){} };`
メソッド記法です。プロパティに関数を定義するとき、非常に簡素で便利な方法です。
`var obj = { method: function(){} };`と*ほぼ*同等です。

```js
var obj = {
  method(){ alert("！"); },
  "my method"(){ alert("！"); }, // method の代わりに上で挙げたような書き方が可能
  0(){ alert("！"); }, // 〃
  [!true](){ alert("！"); } // 〃
};
```

###細かな補足: `{method(){}}`と`{method:function(){}}`の違い
`var obj = { method(){} };`は`var obj = { method: function(){} };`の単なる簡易的な書き方と思いがちですが、実はそうではありません。
相違点がいくつかあります。

* `{ method(){} }`はコンストラクタとして実行できない。つまり、`prototype`プロパティを持たず、new できない。
* `{ method(){} }`はsuperキーワードが使える。
* `{ method(){} }`のパラメータに同じ名前を指定してしまうと、気を利かせてエラーにしてくれる。

```js
var obj = {
  method1(){},
  method2: function(){}
};
console.log( typeof obj.method1.prototype ); // "undefined"
console.log( typeof obj.method2.prototype ); // "object"
/* new obj.method1(); */ // コンストラクタとして実行できない
new obj.method2();

obj = {
  prop: 42,
  hasOwnProperty(v){ return super.hasOwnProperty(v) + "!"; }
/* hasOwnProperty: function(v){ return super.hasOwnProperty(v) + "!"; } */ // super キーワードが使えない
};
console.log( obj.hasOwnProperty("prop") ); // "true!"

obj = {
/* method1(a, a){}, */ // パラメータに同じ名前は指定できない
  method2: function(a, a){}
};
```


#`var obj = { get prop(){ return value; } };`
ゲッターです。`obj.prop`と書くとあたかも普通のプロパティのように値を取得できます。
この記法は決して新しいものではなく、ES5から存在しました。IE9でも書くことができます。

```js
var obj = {
  get prop(){ return Math.random(); },
  get "my prop"(){ return Math.random(); }, // prop の代わりに上で挙げたような書き方が可能
  get 0(){ return Math.random(); }, // 〃
  get [!true](){ return Math.random(); } // 〃
};
console.log( obj.prop ); // アクセスする度に異なる値が返ってくる
console.log( obj.prop );
console.log( obj.prop );
```


#`var obj = { set prop(v){ value = v; } };`
セッターです。`obj.prop = 42;`などと書くとあたかも普通のプロパティのように値を設定したりできます。
この記法も決して新しいものではなく、ES5から存在しました。IE9でも書くことができます。

```js
var obj = {
  set prop(v){ alert(v); },
  set "my prop"(v){ alert(v); }, // prop の代わりに上で挙げたような書き方が可能
  set 0(v){ alert(v); }, // 〃
  set [!true](v){ alert(v); } // 〃
};
obj.prop = "！"; // "！" とアラートされる
```

#`var obj = { *generator(){} };`
ジェネレータ関数の簡略表記です。
`var obj = { generator: function*(){} };`と*ほぼ*同等です。

```js
var obj = {
  *generator(){},
  *"my generator"(){}, // generator の代わりに上で挙げたような書き方が可能
  *0(){}, // 〃
  *[!true](){} // 〃
};
```

`{*generator(){}}`と`{generator:function*(){}}`の違いは、メソッド記法の場合とほぼ同じです。ただし、~~ジェネレータではどちらも new できます。~~（→*ECMAScript 6* の次の仕様である *ECMAScript 2016* にて、**ジェネレータは new できないことになりました**。）

* `{ *generator(){} }`はsuperキーワードが使える。
* `{ *generator(){} }`のパラメータに同じ名前を指定してしまうと、気を利かせてエラーにしてくれる。

#これであなたも
オブジェクトリテラルマスター！