export 與 export default


ES6 的模組若要公開名稱,可以使用 export,必須注意的是,為了表示公開的是名稱,必須使用 {} 包含,就算只有一個名稱要公開也是一樣,例如:

let a = 10;

export {a};

這樣的 export 稱為 Named Export,你不可以這麼撰寫:

let a = 10;

export a;  // SyntaxError: Unexpected token export

相對地,在 import 時也必須使用 {} 表示要匯入的是名稱,就算只有匯入一個名稱:

import {a} from './foo';

export 的是名稱,不是被參考的值,因此若名稱後來被指定了新的值,另一個模組匯入後取得的值也會是新的值,例如,如果從下面這個模組匯入了 a,那麼值會是 20:

let a = 10;
export {a};
a = 20;

你可能會想要從某個模組匯入名稱之後,在目前的模組再進行公開,例如:

import {a, b} from './foo';
export {a, b};

一個更方便的寫法是:

export {a, b} from './foo';

若再度公開名稱時必須改名也是可以的:

export {a as x, b as y} from './foo';

如果要公開的是全部的名稱,可以使用 *

export * from './foo';

如果你要匯出一個「值」,可以使用 export default,例如:

export default 10;

一個模組只能有一個 export default,另一個模組要匯入這個值的話,必須指定一個變數,例如:

import a from '.foo';

注意到,這邊使用的是 a 而不是 {a}。由於 export default 匯出的是一個值,因此像是底下的範例:

let x = 10;
export default x;
x = 20;

實際上被 export default 的是 x 的值 10,因而後續將 x 設為 20,匯入此模組的另一模組,得到的值並不會是 20,一個模組可以同時有多個 export 與一個 export default

export default 可以讓模組的客戶端,在不知道模組中匯出了哪個名稱的情況下,就能自訂名稱取用模組功能,例如,export default 一個工廠函式,之後使用該工廠函式來取用模組名稱:

// 模組功能實作
...

// 提供工廠函式
function factory(...) {
    ....
}

export default factory;

另一模組可以自訂工廠函式名稱,例如:

import XD from './foo';

XD('id').html('<b>這只是個示範</b>');

也許你會想到,export default 一個物件,讓該物件作為名稱空間:

export default {
    f1 : function(...) {...},
    f2 : function(...) {...},
    ...
};

雖然客戶端最後可以像過去那種,以單一物件作為名稱空間的方式來使用此模組的功能,然而,ES6 並不鼓勵使用這種方式,理由是被 import 的物件無法靜態分析,在必要的時候進行最佳化之類。

export default 的本質上,其實是使用 default 作為公開的名稱,而 default 的值就是 export default 後指定的值,因此,也可以使用底下方式來 import

import {default as a} from './foo';

因此,如果你匯入了某個模組,想要直接匯出該模組的 default,可以如下:

export {default} from './math';

如果撰寫了底下的程式:

import a from './foo';
export {a as x};

那麼可以直接改為:

export {default as x} from './foo';

如果撰寫了底下的程式:

import {a} from './foo';
export default {a};

那麼可以改為:

export {a as default} from './foo';