ECMAScript6の新機能

以下はGithubで2万☆を獲得している、[Overview of ECMAScript 6 features](https://github.com/lukehoban/es6features)というコンテンツの日本語訳です。

# Introduction

ECMAScript2015とも言われているECMAScript6は、ECMAScript標準の最新バージョンです。
ES6は、2009年に標準化されたES5以来、初めての重要なアップデートになります。
主要なJavaScriptエンジンにおいて、現在これら新機能の[実装が進行中](http://kangax.github.io/compat-table/es6/)です。

ES6の完全な仕様については、[ES6 standard](http://www.ecma-international.org/ecma-262/6.0/)を参照してください。
ES6には、以下のような新機能が含まれています。

# ECMAScript 6 Features

## arrows

アロー`=>`は、`function`の省略表記で、C#、Java8やCoffeeScriptのアローと似たような構文で書けるよ。
式と文どちらの書き方もサポートするよ。
呼び出し方で`this`が変わる`function`とは違い、アローの`this`は常にその周囲と同じスコープになるよ。

```js
	// 式
	var odds = evens.map(v => v + 1);
	var nums = evens.map((v, i) => v + i);
	var pairs = evens.map(v => ({even: v, odd: v + 1}));

	// 文
	nums.forEach(v => {
	  if (v % 5 === 0)
	    fives.push(v);
	});

	// thisのスコープ
	var bob = {
	  _name: "Bob",
	  _friends: [],
	  printFriends() {
	    this._friends.forEach(f =>
	      console.log(this._name + " knows " + f));
	  }
	}
```

より詳細は[MDN Arrow Functions](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions)を参照すること。

## classes

ES6のクラス構文は、プロトタイプベース言語をオブジェクト指向に見せかけるシンタックスシュガーです。
ひとつ便利な定義を追加することで、クラス構文が使いやすくなり相互運用性も高まります。
クラスは継承、super、インスタンスメソッドとクラスメソッド、コンストラクタをサポートします。

```js
	class SkinnedMesh extends THREE.Mesh {
	  
	  // コンストラクタ
	  constructor(geometry, materials) {
	    // super.constructor()
	    super(geometry, materials);

	    this.idMatrix = SkinnedMesh.defaultMatrix();
	    this.bones = [];
	    this.boneMatrices = [];
	    //...
	  }
	  // インスタンスメソッド
	  update(camera) {
	    //...
	    super.update();
	  }
	  // getter
	  get boneCount() {
	    return this.bones.length;
	  }
	  //setter
	  set matrixType(matrixType) {
	    this.idMatrix = SkinnedMesh[matrixType]();
	  }
	  // クラスメソッド
	  static defaultMatrix() {
	    return new THREE.Matrix4();
	  }
	}
```

より詳細は[MDN Classes](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes)を参照すること。

## enhanced object literals

オブジェクトリテラルは`foo:foo`の省略、メソッド定義、`super()`、プロパティ名の演算などに対応しました。
オブジェクトリテラルとクラス構文を一緒に利用することで、これらがより便利に扱えるようになります。

```js
var obj = {
    // __proto__
    __proto__: theProtoObj,
    // handler: handlerの略
    handler,
    // メソッド
    toString() {
      // theProtoObj.toString()を呼んでる
      return "d " + super.toString();
    },
    // 計算結果をプロパティ名にできる
    [ 'prop_' + (() => 42)() ]: 42
};
```

より詳細は[MDN Grammar and types: Object literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Object_literals)を参照すること。

## template strings

テンプレートリテラルは文字列を作成するためのシンタックスシュガーです。
これはPerlやPythonなどのヒアドキュメントと似ています。
オプションで、タグを付けることで文字列作成をカスタマイズすることができます。
インジェクション攻撃を防いだり、より高度な文字列作成ができるでしょう。

```js
	// 基本
	`In JavaScript '\n' is a line-feed.`

	// 複数行
	`In JavaScript this is
	 not legal.`

	// 文字列展開
	var name = "Bob", time = "today";
	`Hello ${name}, how are you ${time}?`

	// POST関数が呼ばれる
	POST`http://foo.org/bar?a=${a}&b=${b}
	     Content-Type: application/json
	     X-Credentials: ${credentials}
	     { "foo": ${foo},
	       "bar": ${bar}}`(myOnReadyStateChangeHandler);
```

より詳細は[MDN Template Strings](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)を参照すること。

## destructuring

分割代入は配列とオブジェクトによるバインディングをサポートしています。
分割代入は`foo["bar"]`の参照と同じようにフェールセーフで、値がなかったら`undefined`を返します。

```js
	// 配列
	var [a, , b] = [1,2,3];

	// オブジェクト
	var { op: a, lhs: { op: b }, rhs: c }
	       = getASTNode()

	// オブジェクトの短縮形
	var {op, lhs, rhs} = getASTNode()

	// 引数
	function g({name: x}) {
	  console.log(x);
	}
	g({name: 5})

	// フェールソフト
	var [a] = []; // a === undefined

	// デフォルト値があればそっちになる
	var [a = 1] = []; // a === 1
```

より詳細は[MDN Destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)を参照すること。

## default + rest + spread

関数呼び出し時に引数が無かった場合はデフォルト値が使用される。。
呼び出される方に書く`...`はRest parametersと呼ばれ、余った引数が全て配列で入ってくる。
呼び出す方に書く`...`はスプレッド演算子と呼ばれ、配列を展開して呼び出し先に渡される。

```js
	function f(x, y=12) {
	  // 第二引数が無いかundefinedのときはy=12になる
	  return x + y;
	}
	f(3) // 15
	
	function f(x, ...y) {
	  // y = ["hello", true]になる
	  return x * y.length;
	}
	f(3, "hello", true) // 6
	
	function f(x, y, z) {
	  return x + y + z;
	}
	// f(1, 2, 3)と同じ
	f(...[1, 2, 3]) // 6
```

より詳細はMDN [Default parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters)、[Rest parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters)、[Spread Operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator)を参照すること。

## let + const

letはブロックスコープのvarで再代入可能。
constは再代入不可能。

```js
	function f() {
	  {
	    let x;
	    
	    {
	      // {}内のスコープになるので定義可能
	      const x = "sneaky";
	      // constは再代入不可なのでエラーになる
	      x = "foo";
	    }
	    
	    // 同スコープで既にletしてるのでエラーになる
	    let x = "inner";
	    // 再代入はOK
	    x = "inner";
	  }
	}
```

より詳細はMDN [let statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let)、[const statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const)を参照すること。

## iterators + for..of

イテレータは[IEnumerable](https://msdn.microsoft.com/ja-jp/library/system.collections.ienumerable.aspx)や[Iterable](https://docs.oracle.com/javase/jp/8/docs/api/java/lang/Iterable.html)のように反復処理をカスタマイズできます。
`for-of`を使うと、`for-in`より簡単にイテレータから値を取り出せます。
特に何もしなくてもLINQのように遅延評価されます。

```js
	let fibonacci = {
	  [Symbol.iterator]() {
	    let pre = 0, cur = 1;
	    return {
	      next() {
	        [pre, cur] = [cur, pre + cur];
	        return { done: false, value: cur }
	      }
	    }
	  }
	}

	for (var n of fibonacci) {
	  // 1000で終了
	  if (n > 1000)
	    break;
	  console.log(n);
	}
```

イテレータのinterfaceを[TypeScript](http://www.typescriptlang.org/)で書くと以下のようになります。

```js
	interface IteratorResult {
	  done: boolean;
	  value: any;
	}
	interface Iterator {
	  next(): IteratorResult;
	}
	interface Iterable {
	  [Symbol.iterator](): Iterator
	}
```

より詳細は[MDN for...of](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of)を参照すること。

## generators

ジェネレータは、`function*`と`yield`を使ってイテレータを簡単に作れる機能です。
`function*`で宣言した関数はGeneratorインスタンスを返します。
ジェネレータは`next`と`throw`を持ったイテレータのサブタイプで、`yield`で関数は動いたまま値を返します(もしくはthrowする)。

注：イテレータを使うとES7の`await`みたいなこともできるよ

```js
	var fibonacci = {
	  [Symbol.iterator]: function*() {
	    var pre = 0, cur = 1;
	    for (;;) {
	      var temp = pre;
	      pre = cur;
	      cur += temp;
	      yield cur;
	    }
	  }
	}

	for (var n of fibonacci) {
	  // 1000で終了
	  if (n > 1000)
	    break;
	  console.log(n);
	}
```

ジェネレータのinterfaceを[TypeScript](http://www.typescriptlang.org/)で書くと以下のようになります。

```js
	interface Generator extends Iterator {
	    next(value?: any): IteratorResult;
	    throw(exception: any);
	}
```

より詳細は[MDN Iteration protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)を参照すること。

## unicode

ユニコードリテラル、RegExpのUnicodeフラグ、21ビットのコードポイントAPIなど、Unicodeサポートを強化しました。
これらにより、JavaScriptでグローバルなアプリ作成が容易になります。

```js
	// これまでと同じ
	"𠮷".length == 2

	// Unicodeフラグ
	"𠮷".match(/./u)[0].length == 2

	// Unicodeリテラル
	"\u{20BB7}"=="𠮷"=="\uD842\uDFB7"

	// String.prototype.codePointAt()
	"𠮷".codePointAt(0) == 0x20BB7

	// イテレータ
	for(var c of "𠮷") {
	  console.log(c);
	}
```

より詳細は[MDN RegExp.prototype.unicode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode)を参照すること。

## modules

コンポーネント定義のモジュールを言語レベルでサポートしました。
一般的な[AMD](https://github.com/amdjs/amdjs-api/blob/master/AMD.md)や[CommonJS](http://www.commonjs.org/)みたいな形で書けます。
モジュールは非同期で、必要とされるまで中のコードは実行されません。

```js
	// lib/math.js
	export function sum(x, y) {
	  return x + y;
	}
	export var pi = 3.141593;
	
	// app.js
	import * as math from "lib/math";
	alert("2π = " + math.sum(math.pi, math.pi));
	
	// otherApp.js
	import {sum, pi} from "lib/math";
	alert("2π = " + sum(pi, pi));
```

追加機能としては、`export default`と`export *`があります。

```js
	// lib/mathplusplus.js
	export * from "lib/math";
	export var e = 2.71828182846;
	export default function(x) {
	    return Math.log(x);
	}
	
	// app.js
	import ln, {pi, e} from "lib/mathplusplus";
	alert("2π = " + ln(e)*pi*2);
```

より詳細は[MDN import statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)、[export statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export)を参照すること。

## module loaders

モジュールローダは以下をサポートします。
・動的ローディング
・状態の分離
・グローバル領域を使わない
・コンパイル時フック
・仮想化のネスト

デフォルトのローダを変更することができ、また新しいローダを作成することもできます。

```js
	// 動的ローディング 'System'はデフォルトのローダ
	System.import('lib/math').then(function(m) {
	  alert("2π = " + m.sum(m.pi, m.pi));
	});

	// 新しいローダ
	var loader = new Loader({
	  global: fixup(window) // 'console.log'を差し替える
	});
	loader.eval("console.log('hello world!');");

	// モジュールを直接操作
	System.get('jquery');
	System.set('jquery', Module({$: $})); // WARNING: not yet finalized
```

## map + set + weakmap + weakset

一般的なアルゴリズムに対して効率的なデータ構造。
WeakMapはメモリリークのない、オブジェクトをキーとするKey-Valueストアです。

```js
	// Set
	var s = new Set();
	s.add("hello").add("goodbye").add("hello");
	s.size === 2;
	s.has("hello") === true;

	// Map
	var m = new Map();
	m.set("hello", 42);
	m.set(s, 34);
	m.get(s) == 34;

	// WeakMap
	var wm = new WeakMap();
	wm.set(s, { extra: 42 });
	wm.size === undefined

	// WeakSet
	var ws = new WeakSet();
	ws.add({ data: 42 });
	// Weak*以外から参照がない場合、キーはGCされる
```

より詳細はMDN [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)、[Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set)、[WeakMap](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)、[WeakSet](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet)を参照すること。

## proxies

Proxyを使うと、おおよそあらゆるオブジェクトを上書きして挙動を変更することが可能になります。
傍受、オブジェクトの仮想化、ロギングなどに使用できるでしょう。

```js
	// 普通のObject
	var target = {};
	var handler = {
	  get: function (receiver, name) {
	    return `Hello, ${name}!`;
	  }
	};
	
	// targetをhandlerで上書き
	var p = new Proxy(target, handler);
	p.world === 'Hello, world!';
	
	// 普通の関数
	var target = function () { return 'I am the target'; };
	var handler = {
	  apply: function (receiver, ...args) {
	    return 'I am the proxy';
	  }
	};
	
	// targetをhandlerで上書き
	var p = new Proxy(target, handler);
	p() === 'I am the proxy';
```

ランタイムレベルの操作も上書きできます。

```js
	var handler =
	{
	  get:...,
	  set:...,
	  has:...,
	  deleteProperty:...,
	  apply:...,
	  construct:...,
	  getOwnPropertyDescriptor:...,
	  defineProperty:...,
	  getPrototypeOf:...,
	  setPrototypeOf:...,
	  enumerate:...,
	  ownKeys:...,
	  preventExtensions:...,
	  isExtensible:...
	}
```

より詳細は[MDN Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)を参照すること。

## symbols

SymbolはObjectに対するアクセス制御を可能にします。
SymbolはObjectのキーとして設定できる、新しいプリミティブ型です。
引数descriptionを渡せますが、必須ではありません。
Symbolはgensymのように一意ですが、Object.getOwnPropertySymbolsで列挙できるのでprivateではありません。

```js
	var MyClass = (function() {

	  // Symbol
	  var key = Symbol("key");
	  
	  // キーにする
	  function MyClass(privateData) {
	    this[key] = privateData;
	  }

	  MyClass.prototype = {
	    doStuff: function() {
	      ... this[key] ...
	    }
	  };

	  return MyClass;
	})();
	
	var c = new MyClass("hello");
	// MyClass.keyとは別物なので参照不可
	c["key"] === undefined;
```

より詳細は[MDN Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)を参照すること。

## subclassable built-ins

ES6ではArray、Date、DOM Elementsのような組み込み関数を継承できます。
オブジェクト生成時に`Ctor`という関数が呼ばれ、以下の処理を行います。
・`Ctor[@@create]`を呼んでオブジェクトを生成する
・`constructor`を呼んでインスタンスを生成する

`Symbol.create`で既知の`@@create`を利用できます。
組み込み関数は`@@create`を公開しています。

```js
	// Arrayの擬似コード
	class Array {
	    constructor(...args) { /* ... */ }
	    static [Symbol.create]() {
	        // Install special [[DefineOwnProperty]] to magically update 'length'
	    }
	}

	// Arrayのサブクラス
	class MyArray extends Array {
	    constructor(...args) { super(...args); }
	}

	// newすると`@@create`、`constructor`を順に呼び出す
	var arr = new MyArray();
	arr[1] = 12;
	arr.length == 2
```

## math + number + string + array + object APIs

Mathライブラリ、配列変換、文字列操作、Object.assignなど多くのライブラリが追加されました。

```js
	Number.EPSILON;
	Number.isInteger(Infinity); // false
	Number.isNaN("NaN"); // false

	Math.acosh(3); // 1.762747174039086
	Math.hypot(3, 4); // 5
	Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2); // 2

	"abcde".includes("cd"); // true
	"abc".repeat(3); // "abcabcabc"

	Array.from(document.querySelectorAll('*')); // Arrayを返す
	Array.of(1, 2, 3); // new Array()とほぼ同じだが、引数が一つのときに動作が変わらない
	[0, 0, 0].fill(7, 1); // [0,7,7]
	[1, 2, 3].find(x => x == 3); // 3
	[1, 2, 3].findIndex(x => x == 2); // 1
	[1, 2, 3, 4, 5].copyWithin(3, 0); // [1, 2, 3, 1, 2]
	["a", "b", "c"].entries(); // [0, "a"], [1,"b"], [2,"c"]のイテレータ
	["a", "b", "c"].keys(); // 0, 1, 2のイテレータ
	["a", "b", "c"].values(); // "a", "b", "c"のイテレータ

	Object.assign(Point, { origin: new Point(0,0) })
```

より詳細はMDN [Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)、[Math](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math)、[Array.from](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from)、[Array.of](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/of)、[Array.prototype.copyWithin](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin)、[Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)を参照すること。

## binary and octal literals

数値リテラルに2進数表記bと8進数表記oが追加されました。

```js
	0b111110111 === 503 // true
	0o767 === 503 // true
```

## promises

Promiseは非同期処理を行う第一級関数ライブラリです。
Promiseは既に多くのJavaScriptライブラリで使用されています。

```js
	function timeout(duration = 0) {
	    return new Promise((resolve, reject) => {
	        setTimeout(resolve, duration);
	    })
	}

	var p = timeout(1000).then(() => {
	    return timeout(2000);
	}).then(() => {
	    throw new Error("hmm");
	}).catch(err => {
	    return Promise.all([timeout(100), timeout(200)]);
	})
```

より詳細は[MDN Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)を参照すること。

## reflect api

リフレクションAPIはObjectに対するメタ操作を可能とします。
これはProxy APIの逆みたいなもので、Proxy同様呼び出しをフックできます。
Proxyの実装に特に便利です。

```
	// サンプルはないよ
```

より詳細は[MDN Reflect](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect)を参照すること。

## tail calls

末尾再帰を最適化します。
再帰的なアルゴリズムに無限の入力があっても今後は安心です。

```js
	function factorial(n, acc = 1) {
	    'use strict';
	    if (n <= 1) return acc;
	    return factorial(n - 1, n * acc);
	}

	// 今はStack overflowが起こるけど、ES6では安全になる
	factorial(100000)
```


# 感想

PHP5.0からPHP5.3に進化したみたいなかんじ？

正直ES6よくわかってないので、読んでもわからないところが多かった。
というかこのGithub全体的にあまりに端折りすぎてて、詳細を見ない限り機能が存在することくらいしかわからない。
さらに更新が一年前から止まっていて、大量の[プルリク](https://github.com/lukehoban/es6features/pulls)も放置状態。
どうして2万も☆がついてるのかよくわからない。

あと`Ctor[@@create]`が何なのか全くわからなかった。