ES6のexportについて詳しく調べた

# ES6のexportについて
webpackのチュートリアルとかがES6なので、読めないとやばい、開発のときは書けないとやばいということで調べてみました。

## exportについて
モジュール化を行うexportには、モジュールごとに複数のexportを行うnamed exportsとモジュールごとに1つのexportを行うdefault exportsがある。

### named exports
モジュールは前言の先頭に`export`とつけることで、複数のモジュールをexportすることができる。

```js:lib.js
export const sqrt = Math.sqrt;
export function square(x) {
  return x * x;
}
export function diag(x, y) {
  return sqrt(square(x) + square(y));
}
```

```js:main.js
import { square, diag } from 'lib'; //libからsquareとdiagというモジュールをインポートする
console.log(square(11));
console.log(diag(4, 3));
```

モジュール全体をインポートして、named exportsをプロパティ表記法で参照することもできる。

```js
import * as lib from 'lib'; // lib.jsの全てのモジュールをlibというオブジェクトに格納するみたいなイメージ
console.log(lib.square(11));
console.log(lib.diag(4, 3));
```

CommonJSと同じ記述で、Node.jsのモジュールのエクスポートと重複しないようにも書ける。

```js:lib.js
var sqrt = Math.sqrt;
function square(x) {
  return x * x;
}
function diag(x, y) {
  return sqrt(square(x) + square(y));
}
module.exports = {
  sqrt: sqrt,
  square: square,
  diag: diag,
};
```

```js:main.js
var square = require('lib').square;
var diag = require('lib').diag;
console.log(square(11));
console.log(diag(4, 4);
```

### Default exports
フロントの開発でも、1つのモデルに付き1つのモジュールでコンストラクタやクラスが使われる。
ES6のモジュールは、最も重要なexportする値default exportという形で選択できる。

```js:myFunc.js
export default function() {...};
```

```js:main1.js
import myFunc from 'myFunc';
myFunc();
```

default exportsを使ったクラスのモジュールはこんな感じ。

```js:myClass.js
export default class {...};
```

```js:main2.js
import MyClass from 'MyClass';
let inst = new MyClass();
```

default exportの式の宣言は名前を持たない。
代わりに、モジュールの名前で識別する。

### 名前付きのDefault exports
ライブラリは単一の関数だが、追加のサービスはその関数のプロパティを通して提供される。
// ドキュメントを読んでもピンとこなかったのであとで調べます。

ドキュメントでは、CommonJSでのjQueryとUnderscope.jsの例があった。

```js:underscore.js
var _ = function(obj) {
  ...
};
var each = _.each = _.forEach = function(obj, iterator, context) {
  ...
};
module.export = _;
```

```js:main.js
var _ = require('underscope');
var each = _.each;
```

今や上記のCommonJSはES6モジュールとして書き直されている。
CommonJSよりもES6の方がフラットフラット

```js:underscore.js
export default function(obj) {
  ...
};
export function each(obj, iterator, context) {
  ...
}
export { each as forEach };
```

```js:main.js
import _, { each } from 'underscore';
```

### default exportはnamed exportでもある
default exportは、実はdefaultという名前のエクスポート。
以下は同じ意味になる。

```js
import { default as foo } from 'lib';
import foo from 'lib';
```

同じように以下の2つのモジュールも同義。

```js:module1.js
export default 123;
```

```js:module2.js
const D = 123;
export { D as default };
```

## ES6のモジュールのデザインのゴール

1. default exports推奨
2. 静的なモジュール構成
3. 同期と非同期両方のローディングをサポート
4. モジュール間の巡回依存のサポート

英語力がなかったのと、イメージがつかめなかったのとであまり理解できず。。。。
あとで読み直す( http://2ality.com/2014/09/es6-modules-final.html )

## import方法
ES6ではモジュールのimport方法はいくつかある。

```js
// Default exports and named exports
import theDefault, { named1, named2 } from 'src/mylib';
import theDefault from 'src/mylib';
import { named1, named2 } from 'src/mylib';

// Renaming import named1 as myNamed1
import { named1 as myNamed1, named2 } from 'src/mylib';

// Importing the module as an object
//(with one property per named export)
import * as mylib from 'src/mylib';

// Only load the module, don't import anything
import 'src/mylib';
```

## export方法
モジュールの中にあるものをエクスポートする方法は2つある。
exportで宣言を行う。

```js
export var myVar1 = ...;
export let myVar2 = ...;
export const MY_CONST = ...;

export function myFunc() {
  ...
}
export function* myGeneratorFunc() {
  ...
}
export class MyClass {
  ...
}
```

default exportは関数やクラスを含む式。

```js
export default 123;
export default function (x) {
  return x;
};
export default x => x;
export default class {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
};
```

モジュールの最後にエキスポートしたい全てを羅列できる。

```js
const MY_CONST = ...;
function myFunc() {
  ...
}

export { MY_CONST, myFunc };
```

別の名前でもエキスポートできる。

```js
const MY_NAME = ...;
function myFunc() {
  ...
}

export { MY_CONST as THE_CONST, myFunc as theFunc };
```

### Re-exporting
Re-exportingとは、別のモジュールのエクスポートを現在のモジュールのエクスポートに追加すること。
他のモジュールの全てのエクスポートを追加することもできる。

```js
export * from 'src/other_module';
```

より選択的なRe-exporting

```js
export { foo, bar } from 'src/other_module';

// Export other_modules’s foo as myFoo
export { foo as myFoo, bar } from 'src/other_module';
```

## ES6のモジュールローダー API
モジュールを扱う宣言の文法に加えて、APIもある。
APIでは以下のことができるようになる。

* プログラムに依るモジュールとスクリプトの操作
* モジュールの読み込みの設定
* 
ローダーは、import … fromのモジュールの指示詞に従ってモジュールの読み込みなどの処理を行う。
コンストラクタはReflect.Loader。
各プラットフォームは、モジュールロードの得知恵のスタイルを実装するグローバル変数System（システムローダー）にカスタマイズされたインスタンスを保持する。

### モジュールのインポート
プログラムでのモジュールのインポート。

```js
System.import('some_module')
.then(some_module => {
  // Use some_module
})
.catch(error => {
  ...
});
```

System.import()は以下を可能にする。

- scriptタグの中でモジュールが使えるようになる
- 条件に合わせてモジュールを読み込める

System.importでは、単一のモジュールを取得する。
Promise.allを使用すると複数のモジュールをインポートできる。

```js
Promese.all(
  ['module1', 'module2', 'module3']
  .map(x => System.import(x)))
.then(([module1, module2, module3]) => {
  // User module1, 2, 3
});
```