2016-01-31追記
この記事を最初に書いた頃は他に何も情報がありませんでしたが、今ではよりだいぶわかりやすい資料が出揃ってきました。しっかりとしたimport/exportの仕様をもっと知りたい場合は下記を参照することを推奨します
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/import
- http://www.slideshare.net/teppeis/effective-es6
- http://uehaj.hatenablog.com/entry/2015/11/07/001848
2015/12/05追記
コメント欄より
Babel v6 から Babel 公式の transform である transform-es2015-modules-commonjs を使った場合 ES6 の export default を出力したときに exports.default に変更されてしまいました。
もし以前のように module.exports として出力したい場合は add-module-exports を使う必要がありそうです。
Babelのversion upに伴い、この記事の情報は一部古くなっている部分が出てきました。ご注意下さい。
ES6のimportやらexportやら。こんな感想を持った。
- なんかpythonっぽい
- pythonのあれもいまいちよくわからん
なんとなーくこういうことなんだろうなというのはわかりつついまいち理解できてない。
Draftとかちゃんと追えるのがいいんだけどなんだか難しい(軟弱)
そうだ、Babelの変換コードを見たら何やるのかわかるんじゃね!?
・・・邪道だなあと自分でも思いつつ、取っ掛かりとしてはよさそうなのでTry it outしてみることにする。
import編
まず読み込む方
普通の使いかた
import "foo"
require("foo");
なるほど。これ左辺無いの使いどころあるのか・・・?
{}でかこむ
import { foo } from "foo"
var foo = require("foo").foo;
おお。これよこれ。でもfooのfooを呼ぶのか。
fromをあわせる
import foo from "foo"
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
var foo = _interopRequire(require("foo"));
おおう。途端に複雑になったか。
いや、ちゃんと見ればそう難しくは無いはず。どうもこういうことらしい
- 基本的にはrequireを普通にしている
-
obj.__esModule
がtrue
であればobj["default"]
を返す。- module.exports.defaultというアレか。
-
__esModule
は他のtranspi特にbabel用ではないのか?ちょっと調べきれなかった。
-
__esModule
が無くてもrequire
されているオブジェクトを返しているだけだ。
*を使う
import * as foo from "foo"
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; };
var foo = _interopRequireWildcard(require("foo"));
微妙に違う。
- objectそのものを
foo
に当てているようだ。 -
__esModule
でなければdefault
のプロパティに元のobjectが入っているobjectを返すらしい。
{ as }で囲んでみる
import {oof as foo} from "foo";
var foo = require("foo").oof;
なるほど。asの後が変数。
欄外 import 'utility' as utils;
みたいなやつ
このあたりを調べていると
http://www.sitepoint.com/understanding-es6-modules/
ここで上記のような記載がされていた。
が、どうもこれはコンパイル通っていない。策定前の話だろうか?
export編
次はmodule書く方。
export
とdefault
を組み合わせていく。
export default function
export default function(){
}
module.exports = function () {};
うん、わかりやすい。今までっぽい書き方はこうやるのね。
export function
じゃあdefaultをつけないと?
export function foo(){
console.log("foo")
}
exports.foo = foo;
Object.defineProperty(exports, "__esModule", {
value: true
});
function foo() {
console.log("foo");
}
ほほーん。また複雑な感じ。
-
Object.defineProperty
で__esModulesを設定している。 -
import foo from "foo"
で呼ばれているのがこれなんだろう。 - loose modeだと
exports.__esModule = true
- IE8だと動かない問題ありそう。
-
module.exports
ではなくなるのね。
{} で囲んでみる
function foo() {
}
function baz(a, b) {
}
export { foo, baz }
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function foo() {}
function baz(a, b) {}
exports.foo = foo;
exports.baz = baz;
- definePropertyまわりはいままでと一緒。
- exportsに色々突っ込んでいる。
as を使う
function foo() {
}
export { foo as oof}
Object.defineProperty(exports, "__esModule", {
value: true
});
function foo() {}
exports.oof = foo;
単純にこれは当て込む変数を変えているだけっぽい
{}とdefaultを組み合わせる
function foo() {
}
export default { foo : foo }
"use strict";
function foo() {}
module.exports = { foo: foo };
こうするとたまによくやるmodule.exports.foo
とかの代わりに使える。
まとめ
ここまでをざっくり表にしてみるとこんな感じ
(一部表の都合で簡略化しているのはご了承)
import
EcmaScript6 | Babel |
---|---|
import "foo" |
require("foo"); |
import { foo } from "foo" |
var foo = require("foo").foo; |
import foo from "foo" |
var foo = require("foo") (*) |
import * as foo from "foo" |
var foo = { "default" : require("foo")} (*) |
import {oof as foo} from "foo"; |
var foo = require("foo").oof; |
(*) 1行で書けるように略式
export
EcmaScript6 | Babel |
---|---|
export default function(){} |
module.exports = function () {}; |
export function foo(){} |
exports.foo = foo; |
export { foo, baz } |
exports.foo = foo; exports.baz = baz; |
export { foo as oof} |
exports.oof = foo; |