Edited at

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


ES6のexportについて

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


exportについて

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


named exports

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


lib.js

export const sqrt = Math.sqrt;

export function square(x) {
retrun x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}


main.js

import { square, diag } from 'lib'; //libからsquareとdiagというモジュールをインポートする

console.log(square(11));
console.log(diag(4, 3));

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

import * as lib from 'lib'; // lib.jsの全てのモジュールをlibというオブジェクトに格納するみたいなイメージ

console.log(lib.square(11));
console.log(lib.diag(4, 3));

CommonJSと同じ記述で、Node.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,
};


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という形で選択できる。


myFunc.js

export default function() {...};



main1.js

import myFunc from 'myFunc';

myFunc();

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


myClass.js

export default class {...};



main2.js

import MyClass from 'MyClass';

let inst = new MyClass();

default exportの式の宣言は名前を持たない。

代わりに、モジュールの名前で識別する。


名前付きのDefault exports

ライブラリは単一の関数だが、追加のサービスはその関数のプロパティを通して提供される。

// ドキュメントを読んでもピンとこなかったのであとで調べます。

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


underscore.js

var _ = function(obj) {

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


main.js

var _ = require('underscope');

var each = _.each;

今や上記のCommonJSはES6モジュールとして書き直されている。

CommonJSよりもES6の方がフラットフラット


underscore.js

export default function(obj) {

...
};
export function each(obj, iterator, context) {
...
}
export { each as forEach };


main.js

import _, { each } from 'underscore';



default exportはnamed exportでもある

default exportは、実はdefaultという名前のエクスポート。

以下は同じ意味になる。

import { default as foo } from 'lib';

import foo from 'lib';

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


module1.js

export default 123;



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方法はいくつかある。

// 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で宣言を行う。

export var myVar1 = ...;

export let myVar2 = ...;
export const MY_CONST = ...;

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

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

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;
}
};

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

const MY_CONST = ...;

function myFunc() {
...
}

export { MY_CONST, myFunc };

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

const MY_NAME = ...;

function myFunc() {
...
}

export { MY_CONST as THE_CONST, myFunc as theFunc };


Re-exporting

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

他のモジュールの全てのエクスポートを追加することもできる。

export * from 'src/other_module';

より選択的なRe-exporting

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(システムローダー)にカスタマイズされたインスタンスを保持する。


モジュールのインポート

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

System.import('some_module')

.then(some_module => {
// Use some_module
})
.catch(error => {
...
});

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


  • scriptタグの中でモジュールが使えるようになる

  • 条件に合わせてモジュールを読み込める

System.importでは、単一のモジュールを取得する。

Promise.allを使用すると複数のモジュールをインポートできる。

Promese.all(

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