lacolaco

Google Developers Expert for Angular / 技術的なことや技術的じゃないことを書きます

ECMAScriptのimport/exportについてのメモ

js-primerというJavaScriptの本を書く上でES2015のimport/export構文の仕様について気になったところがあって調べたメモ

github.com

デフォルトエクスポートの扱い

まず、デフォルトエクスポートする方法がふたつある。ひとつは専用のexport default文によってエクスポートする方法。

export default function () {} 

また、defaultという名前で名前付きエクスポートすれば、それもデフォルトエクスポートしたことになる。

function foo() {}

export { foo as default };

デフォルトエクスポートがdefaultという固有名がつけられることは、Specの https://www.ecma-international.org/ecma-262/6.0/#sec-exports-static-semantics-exportentries にかかれている。

f:id:lacolaco:20180626135151p:plain

f:id:lacolaco:20180626135151p:plain
default export

デフォルトエクスポートをインポートする方法

デフォルトエクスポートされたものをインポートする方法もいくつかある。ひとつは一番シンプルなデフォルトインポート用の専用構文を使う。

import otherDefault from "other.js";

ところでこれは名前付きインポートで次のように書き換えられる。先程デフォルトエクスポートで書いたように、デフォルトエクスポートはdefaultという固有名でエクスポートされていることを利用できる。

import { default as otherDefault } from "other.js";

この構文、MDNのimport文のところには書かれていない。

developer.mozilla.org

ちなみに、default asというのは専用の構文ではなく、asによるエイリアス付きインポートの構文が適用されており、仕様上ではdefaultは特別なキーワードではなくただのIdentifierNameとして扱われているはず。 次のコードでdefaultとfooは仕様上同じもので区別できない。

import { default as otherDefault, foo as otherFoo } from "other.js";

https://www.ecma-international.org/ecma-262/6.0/#sec-imports-static-semantics-boundnames

f:id:lacolaco:20180626135841p:plain

しかし、次のコードはシンタックスエラーになる。asによるエイリアスを使わない場合には、defaultfooは等価ではなくなる。 なぜならdefaultECMAScript予約語であるからだ。

import { default, foo } from "other.js";

https://www.ecma-international.org/ecma-262/6.0/#sec-keywords

ここの肝は、Import構文のImportsListというもので、これはImportSpecifierのリストだが、ImportSpecifierはImportedBindingあるいはidentifierName as ImportedBinding と定義されている。

https://www.ecma-international.org/ecma-262/6.0/#sec-imports

f:id:lacolaco:20180626140548p:plain

つまり、import { default } と書いたときのdefaultImportedBindingとして扱われるが、これはシンボルとして参照可能なので予約語のチェックに違反する。

一方で、import { default as alias }と書いたときのdefaultidentifierNameであって、ImportedBindingではなくなり、予約語のチェックから外れる。

結果的に、default asはまるで普通のエイリアスされた名前付きインポートのように振る舞うことができる。 しかし仕様上はimport { default as ...}構文というのは存在していないが、デフォルトエクスポートや予約語の仕様が絡んだ結果、事実上の構文っぽいものになっているのがややこしい。

MDNの構文例はexportとimportどちらも、デフォルトエクスポートがdefaultという名前付きエクスポートとして振る舞っている例を扱っていないが、 これは仕様が複雑で説明が難しいからされてないんだろうか。

とりあえず自分の中で整理がついたので良し。