在建立 JavaScript 模組時,export 語句用於從模組中導出實時系結的函數、物件或原始值,以便其他程式可以通過 import 語句使用它們。被導出的系結值依然可以在本地進行修改。在使用 import 進行匯入時,這些系結值只能被匯入模組所讀取,但在 export 導出模組中對這些系結值進行修改,所修改的值也會實時地更新。
無論您是否宣告,導出的模組都處於嚴格模式。 export 語句不能用在嵌入式指令碼中。
// 導出單個特性
export let name1, name2, …, nameN; // also var, const
export let name1 = …, name2 = …, …, nameN; // also var, const
export function FunctionName(){...}
export class ClassName {...}
// 導出列表
export { name1, name2, …, nameN };
// 重新命名導出
export { variable1 as name1, variable2 as name2, …, nameN };
// 解構導出並重新命名
export const { name1, name2: bar } = o;
// 預設導出
export default expression;
export default function (…) { … } // also class, function*
export default function name1(…) { … } // also class, function*
export { name1 as default, … };
// 合併 modules
export * from …; // does not set the default export
export * as name1 from …;
export { name1, name2, …, nameN } from …;
export { import1 as name1, import2 as name2, …, nameN } from …;
export { default } from …;
靜態的 import 語句用於匯入由另一個模組導出的系結。無論是否宣告瞭 strict mode ,匯入的模組都執行在嚴格模式下。在瀏覽器中,import 語句只能在宣告瞭 type=「module」 的 script 的標籤中使用。
此外,還有一個類似函數的動態 import(),它不需要依賴 type=「module」 的 script 標籤。
在 script 標籤中使用 nomodule 屬性,可以確保向後相容。
在您希望按照一定的條件或者按需載入模組的時候,動態 import() 是非常有用的。而靜態型的 import 是初始化載入依賴項的最優選擇,使用靜態 import 更容易從程式碼靜態分析工具和 tree shaking 中受益。
// 匯入整個模組的內容
import * as myModule from '/modules/my-module.js';
// 匯入單個介面
import {myExport} from '/modules/my-module.js';
// 匯入多個介面
import {foo, bar} from '/modules/my-module.js';
// 匯入帶有別名的介面
import {reallyReallyLongModuleExportName as shortName} from '/modules/my-module.js';
// 匯入時重新命名多個介面
import {
reallyReallyLongModuleMemberName as shortName,
anotherLongModuleName as short
} from '/modules/my-module.js';
// 僅爲副作用而匯入一個模組
// 整個模組僅爲副作用(中性詞,無貶義含義)而匯入,而不匯入模組中的任何內容(介面)。 這將執行模組中的全域性程式碼, 但實際上不匯入任何值。
import '/modules/my-module.js';
// 匯入預設值
import myDefault from '/modules/my-module.js';
import myDefault, * as myModule from '/modules/my-module.js';
// myModule used as a namespace
import myDefault, {foo, bar} from '/modules/my-module.js';
// specific, named imports
// 動態import
import('/modules/my-module.js')
.then((module) => {
// Do something with the module.
});
let module = await import('/modules/my-module.js');
index.mjs
// 第一,將檔案的擴充套件名由 .js 改爲 .mjs;
// 第二,啓動時需要額外新增 `--experimental-modules` 參數;
import { foo, bar } from './module.mjs';
console.log(foo, bar);
// 此時我們也可以通過 esm 載入內建模組了
import fs from 'fs';
fs.writeFileSync('./foo.txt', 'es module working');
// 也可以直接提取模組內的成員,內建模組相容了 ESM 的提取成員方式
import { writeFileSync } from 'fs';
writeFileSync('./bar.txt', 'es module working');
// 對於第三方的 NPM 模組也可以通過 esm 載入
import _ from 'lodash';
_.camelCase('ES Module');
// 不支援,因爲第三方模組都是導出預設成員
// import { camelCase } from 'lodash'
// console.log(camelCase('ES Module'))
commonjs.js
// CommonJS 模組始終只會導出一個預設成員
// module.exports = {
// foo: 'commonjs exports value'
// }
// exports.foo = 'commonjs exports value'
// 不能在 CommonJS 模組中通過 require 載入 ES Module
// const mod = require('./es-module.mjs')
// console.log(mod)
es-module.mjs
// ES Module 中可以匯入 CommonJS 模組
// import mod from './commonjs.js'
// console.log(mod)
// 不能直接提取成員,注意 import 不是解構導出物件
// import { foo } from './commonjs.js'
// console.log(foo)
// export const foo = 'es module export value'
esm.mjs
// ESM 中沒有模組全域性成員了
// // 載入模組函數
// console.log(require)
// // 模組物件
// console.log(module)
// // 導出物件別名
// console.log(exports)
// // 當前檔案的絕對路徑
// console.log(__filename)
// // 當前檔案所在目錄
// console.log(__dirname)
// -------------
// require, module, exports 自然是通過 import 和 export 代替
// __filename 和 __dirname 通過 import 物件的 meta 屬性獲取
// const currentUrl = import.meta.url
// console.log(currentUrl)
// 通過 url 模組的 fileURLToPath 方法轉換爲路徑
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
console.log(__filename);
console.log(__dirname);
Node v12 之後的版本,可以通過package.json
中新增type
欄位爲module
,將預設模組系統修改爲ES Module
,此時就不需要修改副檔名爲.mjs
了
如果需要在type=module
的情況下繼續使用CommonJS
,需要將副檔名修改爲.cjs
對於早期的 Node.js 版本,可以使用 Babel 實現 ES Module 的相容
// 設定:第一種方式
{
"plugins": [
"@babel/plugin-transform-modules-commonjs"
]
}
// 設定:第二種方式(合集)
{
"presets":["@babel/preset-env"]
}