ES6のexportについて
webpackのチュートリアルとかがES6なので、読めないとやばい、開発のときは書けないとやばいということで調べてみました。
exportについて
モジュール化を行うexportには、モジュールごとに複数のexportを行うnamed exportsとモジュールごとに1つのexportを行うdefault exportsがある。
named exports
モジュールは前言の先頭にexport
とつけることで、複数のモジュールをexportすることができる。
export const sqrt = Math.sqrt;
export function square(x) {
return x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}
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のモジュールのエクスポートと重複しないようにも書ける。
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,
};
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という形で選択できる。
export default function() {...};
import myFunc from 'myFunc';
myFunc();
default exportsを使ったクラスのモジュールはこんな感じ。
export default class {...};
import MyClass from 'MyClass';
let inst = new MyClass();
default exportの式の宣言は名前を持たない。
代わりに、モジュールの名前で識別する。
名前付きのDefault exports
ライブラリは単一の関数だが、追加のサービスはその関数のプロパティを通して提供される。
// ドキュメントを読んでもピンとこなかったのであとで調べます。
ドキュメントでは、CommonJSでのjQueryとUnderscope.jsの例があった。
var _ = function(obj) {
...
};
var each = _.each = _.forEach = function(obj, iterator, context) {
...
};
module.export = _;
var _ = require('underscope');
var each = _.each;
今や上記のCommonJSはES6モジュールとして書き直されている。
CommonJSよりもES6の方がフラットフラット
export default function(obj) {
...
};
export function each(obj, iterator, context) {
...
}
export { each as forEach };
import _, { each } from 'underscore';
default exportはnamed exportでもある
default exportは、実はdefaultという名前のエクスポート。
以下は同じ意味になる。
import { default as foo } from 'lib';
import foo from 'lib';
同じように以下の2つのモジュールも同義。
export default 123;
const D = 123;
export { D as default };
ES6のモジュールのデザインのゴール
- default exports推奨
- 静的なモジュール構成
- 同期と非同期両方のローディングをサポート
- モジュール間の巡回依存のサポート
英語力がなかったのと、イメージがつかめなかったのとであまり理解できず。。。。
あとで読み直す( 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
});