export
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since May 2018.
export
宣言は、JavaScript モジュールから値をエクスポートするために使用されます。エクスポートされた値は import
宣言やダイナミックインポートによって、他のプログラムにインポートすることができます。インポートされたバインディングの値は、それをエクスポートするモジュールの変更の対象となります。モジュールがエクスポートするバインディングの値を更新すると、その更新はインポートされた値として見えます。
ソースファイルで export
宣言を使用するためには、そのファイルはランタイムによってモジュールとして解釈される必要があります。HTML では、<script>
タグに type="module"
を追加するか、他のモジュールにインポートされることで実現されます。モジュールは自動的に厳格モードで解釈されます。
構文
// 個々の機能をエクスポート
export let name1, name2/*, … */; // var も
export const name1 = 1, name2 = 2/*, … */; // var, let も
export function functionName() { /* … */ }
export class ClassName { /* … */ }
export function* generatorFunctionName() { /* … */ }
export const { name1, name2: bar } = o;
export const [ name1, name2 ] = array;
// リストをエクスポート
export { name1, /* …, */ nameN };
export { variable1 as name1, variable2 as name2, /* …, */ nameN };
export { variable1 as "string name" };
export { name1 as default /*, … */ };
// デフォルトエクスポート
export default expression;
export default function functionName() { /* … */ }
export default class ClassName { /* … */ }
export default function* generatorFunctionName() { /* … */ }
export default function () { /* … */ }
export default class { /* … */ }
export default function* () { /* … */ }
// モジュールの集約
export * from "module-name";
export * as name1 from "module-name";
export { name1, /* …, */ nameN } from "module-name";
export { import1 as name1, import2 as name2, /* …, */ nameN } from "module-name";
export { default, /* …, */ } from "module-name";
export { default as name1 } from "module-name";
解説
各モジュールでは、2 つの異なる種類のエクスポート、名前付きエクスポートとデフォルトエクスポートを行うことができます。名前付きエクスポートはモジュールごとに複数持てますが、デフォルトエクスポートは 1 つのみです。それぞれのエクスポート方法は、上記の構文のひとつに対応します。
名前付きエクスポート:
// 事前に宣言された機能のエクスポート
export { myFunction2, myVariable2 };
// 個別の機能のエクスポート
// (var, let, const, function, class がエクスポート可能)
export let myVariable = Math.sqrt(2);
export function myFunction() {
// …
}
export
キーワードの後には、 let
, const
, var
宣言や、関数、クラス宣言を使用することができます。また、 export { name1, name2 }
構文を使用すると、他の場所で宣言された名前のリストをエクスポートすることができます。export {}
は空のオブジェクトをエクスポートするわけではないことに注意してください。これは何もエクスポートしない(空の名前のリストをエクスポートする)ノーオペレーション宣言です。
エクスポート宣言は一時的なデッドゾーンのルールには従いません。X
という名前自体が宣言される前に、そのモジュールが X
をエクスポートすることを宣言することができます。
export { x };
const x = 1;
// これは、`export`が単なる宣言であり、`x`の値を利用しないので、
// 動作します。
デフォルトエクスポート:
// デフォルトとして事前に定義された機能のエクスポート
export { myFunction as default };
// これは次のものと同等です
export default myFunction;
// 個別の機能をデフォルトとしてエクスポート
export default function () { /* … */ }
export default class { /* … */ }
メモ: エクスポート宣言の名前は、互いに異なるものでなければなりません。重複した名前でエクスポートを実施したり、default
のエクスポートを複数使用すると SyntaxError
が発生し、モジュールが評価されなくなります。
export default
構文ではあらゆる式が許可されます。
export default 1 + 1;
特殊なケースとして、関数やクラスは式ではなく 宣言 としてエクスポートされ、これらの宣言は無名にすることができます。つまり、関数は巻き上げが行われることになります。
// これは `foo` は関数宣言であって、関数式ではないため動作します。
foo();
export default function foo() {
console.log("Hi");
}
// 厳密には宣言であることに変わりはないが、無名であることが許されます。
export default function () {
console.log("Hi");
}
名前付きエクスポートは、複数の値をエクスポートする必要がある場合に有益です。このモジュールをインポートするときは、名前付きエクスポートでは全く同じ名前で参照しなければなりませんが(任意で as
で名前を変更できます)、デフォルトエクスポートは何か名前を付けてインポートすることができます。例を示します。
// ファイル test.js
const k = 12;
export default k;
// 他のファイル
import m from "./test"; // k がデフォルトエクスポートなので、インポートする k の代わりに m を使用することができる点に注意してください
console.log(m); // 12
名前の競合を防ぐために、名前付きエクスポートの名前を変更することもできます。
export { myFunction as function1, myVariable as variable };
文字列リテラルを使用すると、名前を有効な識別子以外のものに変更することができます。例えば次のようします。
export { myFunction as "my-function" };
再エクスポート / 集約
親モジュール内の異なるモジュールから「インポート/エクスポート」して、そのモジュールからインポートできるようにすることも可能です。言い換えれば、様々なモジュールからの様々なエクスポートを集約した 1 つのモジュールを作成することができます。
これは "export from" 構文で実現できます。
export { default as function1, function2 } from "bar.js";
これは、 function1
と function2
がカレントモジュール内で利用できないことを除けば、import と export の組み合わせと同じです。
import { default as function1, function2 } from "bar.js";
export { function1, function2 };
ほとんどの "import from" 構文には対応する "export from" 構文があります。
export { x } from "mod";
export { x as v } from "mod";
export * as ns from "mod";
また、import * from "mod"
はありませんが、export * from "mod"
はあります。これで mod
からのすべての 名前付き エクスポートが現在のモジュールの名前付きエクスポートとして再エクスポートされますが、 mod
のデフォルトエクスポートは再エクスポートされません。もし、暗黙のうちに同じ名前を再エクスポートする 2 つのワイルドカードの export 文があった場合、どちらも再エクスポートされません。
// -- mod1.js --
export const a = 1;
// -- mod2.js --
export const a = 3;
// -- barrel.js --
export * from "./mod1.js";
export * from "./mod2.js";
// -- main.js --
import * as ns from "./barrel.js";
console.log(ns.a); // undefined
重複した名前を直接インポートしようとすると、エラーが発生します。
import { a } from "./barrel.js";
// SyntaxError: The requested module './barrel.js' contains conflicting star exports for name 'a'
以下は、import に対応するものですが、構文的には無効です。
export DefaultExport from "bar.js"; // Invalid
正しい方法は、エクスポートの名前を変更することです。
export { default as DefaultExport } from "bar.js";
export from" 構文では、as
トークンを省略することができます。これにより、デフォルトエクスポートはデフォルトエクスポートとして再エクスポートされたままとなります。
export { default, function2 } from "bar.js";
export from
は import
が対応しているすべての機能に対応しています。例えばインポート属性などです。
export { default } from "./data.json" with { type: "json" };
例
名前付きエクスポートの使用
my-module.js
モジュールの中で、以下のコードを含めることができます。
// "my-module.js" モジュール
function cube(x) {
return x * x * x;
}
const foo = Math.PI + Math.SQRT2;
const graph = {
options: {
color: "white",
thickness: "2px",
},
draw() {
console.log("From graph draw function");
},
};
export { cube, foo, graph };
HTML ページの中に含まれる最上位モジュールの中では、次のようにすることができます。
import { cube, foo, graph } from "./my-module.js";
graph.options = {
color: "blue",
thickness: "3px",
};
graph.draw(); // "From graph draw function" と記録
console.log(cube(3)); // 27
console.log(foo); // 4.555806215962888
以下の点に注意することが重要です。
デフォルトエクスポートの使用
値をひとつエクスポートしたい、あるいはモジュールでフォールバック先の値を持ちたい場合は、デフォルトエクスポートを使用するとよいでしょう。
// module "my-module.js"
export default function cube(x) {
return x * x * x;
}
別のスクリプトからの、デフォルトエクスポートのインポートは直観的です。
import cube from "./my-module.js";
console.log(cube(3)); // 27
export from の使用
以下のような階層がある場合を例に考えてみましょう。
childModule1.js
:myFunction
およびmyVariable
をエクスポートchildModule2.js
:myClass
をエクスポートparentModule.js
: 集約元として機能する(他には何もしない)- 最上位モジュールである
parentModule.js
のエクスポートを利用する
コードスニペットを使うとこのような感じになります。
// childModule1.js 内
function myFunction() {
console.log("Hello!");
}
const myVariable = 1;
export { myFunction, myVariable };
// childModule2.js 内
class MyClass {
constructor(x) {
this.x = x;
}
}
export { MyClass };
// parentModule.js
// childModule1 と childModule2 からのエクスポートを
// 集約して再エクスポートする
export { myFunction, myVariable } from "childModule1.js";
export { MyClass } from "childModule2.js";
// 最上位モジュール
// parentModule にモジュールが集約しているので、
// 単一のモジュールからエクスポートを利用できます。
import { myFunction, myVariable, MyClass } from "parentModule.js";
仕様書
Specification |
---|
ECMAScript Language Specification # sec-exports |
ブラウザーの互換性
BCD tables only load in the browser
関連情報
import
- JavaScript モジュールガイド
- ES6 in Depth: Modules (hacks.mozilla.org, 2015)
- ES modules: A cartoon deep-dive (hacks.mozilla.org, 2018)
- Exploring JS, Ch.16: Modules (Dr. Axel Rauschmayer)