在使用JavaScript開發大型項目時,模塊開發概念是一個必須考慮的問題。其目的就是通過命名空間對各類業務對象進行一定的封裝,防止命名衝突。 本篇著重介紹ES6 module中的export和import概念。 ...
在使用JavaScript開發大型項目時,模塊開發概念是一個必須考慮的問題。其目的就是通過命名空間對各類業務對象進行一定的封裝,防止命名衝突。
本篇著重介紹ES6 module中的export和import概念。
1. ES5的模塊支持方案
在ES6之前,JavaScript本身沒有模塊支持,但社區創造了令人印象深刻的解決方案。兩個最重要的(也是不相容的)標準是:AMD 和 CommonJS。
1.1 AMD
說明:AMD,全稱為Asynchronous Module Definition,即非同步模塊定義。
特點:其模塊和依賴都可以進行非同步載入。
// 定義AMD模塊 define('User/UserGrid', // 模塊ID ['UserM'], // 依賴文件 function(userM) { // 初始化函數,依賴文件以參數形式加入 } ); // 使用AMD模塊 require(['User/UserGrid'], function(userGrid) { } );
1.2 CommonJS
說明:CommonJS模塊規範初衷是用於node.js伺服器端,以提供額外的功能,如:IO、文件系統等功能。
特點:
①同步載入;只有載入完成,才能執行後面的操作。
②緩存載入;第一次載入時會把內容存入緩存,以後的載入都是從緩存獲取。
示例:
// math.js(定義模塊) exports.add = function(a, b) { return a + b; }; // app.js(使用模塊) var math = require('./math'); var rs = math.add(1, 2); console.log(rs);
瞭解更多AMD 與 CommonJS 知識可參考此文章:Writing Modular JavaScript With AMD, CommonJS & ES Harmony
2. ES6 module
ES6 module 結合了CommonJS和AMD的優點:類似CommonJS,具有簡潔的語法,對迴圈依賴的支持;類似AMD,支持非同步載入和有條件的模塊載入。
ES6 module 使用 export 導出模塊的內容,並使用 import 導入模塊的內容。
2.1 瀏覽器原聲支持
使用之前,先看下各瀏覽器對原生ES6 module的支持情況:Chrome61及61+、Edge16及16+版本都已支持
使用方式:
以Chrome為例,在引入ES6 module 的JS文件時,使用屬性 type="module" 即可:
<script type="module" src="js/math.js"></script> <script type="module" src="js/app.js"></script>
2.2 export 導出(定義模塊)
創建ES6模塊時,可使用export關鍵字導出(對外提供)模塊的內容,如函數、對象以及原始變數等等。
export 導出方案有2種:Named exports(命名導出;每個模塊可有多個)和 Default exports(預設導出;每個模塊只能一個)。
1) Named exports 命名導出
說明:使用 export + 名稱 的形式導出模塊的內容。
註意:在 import 導入過程中,需指定這些名稱。
語法:
// 1)聲明時導出 export var myVar1 = 'a'; export let myVar2 = 'b'; export const MY_CONST = 'c'; export function myFunc() {} // 2)聲明後導出 var myVar3 = 'a'; export { myVar3 }; // 3)別名導出 var myVar4 = 'a'; export { myVar4 as myVar };
示例:
// math.js export function add(a, b) { return a + b; } // app.js:導入含有命名導出的模塊時,需要指定成員名稱 import { add } from './math.js'; console.log(add(1, 2)); // => 3 // demo.html <script type="module" src="js/math.js"></script> <script type="module" src="js/app.js"></script>
2) Default exports 預設導出
說明:使用 export default 導出模塊預設的內容,每個模塊只能有一個 export default。
語法:
// 1)聲明時導出 export default expression; export default function () {} // 2)別名設置為default導出 export default function name1() {} export { name1 as default };
示例:預設導出聲明的是一個表達式,通常沒有名字,導入時需指定模塊名稱。
// math.js export function add(a, b) { return a + b; } export default function cube(x) { return x * x * x; } // app.js:導入預設導出的模塊時,需要指定模塊名稱 import cube from './math.js'; console.log(cube(3)); // => 27 // 若想同時導入含有預設導出、命名導出的模塊,只需要導入時用','隔開 // import cube, { add } from './math.js'; // demo.html <script type="module" src="js/math.js"></script> <script type="module" src="js/app.js"></script>
2.3 import 導入模塊
使用 import 可導入創建的模塊。
語法:
// 1)導入模塊的預設導出內容 import defaultExport from 'module-name'; // 2)導入模塊的命名導出內容 import { export1, export2 } from 'module-name'; import { export as alias } from 'module-name'; // 修改別名 import * as name from 'module-name'; // 導入模塊內的所有命名導出內容 // 3)導入模塊的預設導出、命名導出 import defaultExport, { export1, export2 } from 'module-name'; import defaultExport, * as name from 'module-name';
1) 導入預設導出
說明:導入預設導出的模塊時,需要指定模塊名稱
示例:
// math.js export default function cube(x) { return x * x * x; } // app.js:導入預設導出的模塊時,需要指定模塊名稱 import cube from './math.js'; console.log(cube(3)); // => 27
2) 導入命名導出
說明:導入模塊時可使用大括弧包含指定命名成員;也可以用 * as moduleName 的形式把此模塊的所有命名導出作為某個對象的成員。
示例:
// math.js export function add(a, b) { return a + b; } // app.js:指定使用math模塊的add命名導出 import { add } from './math.js'; console.log(add(1, 2)); // => 3 // 導入所有的命名導出作為math對象的成員 import * as math from './math.js'; console.log(math.add(1, 2)); // => 3
3) 僅導入模塊
說明:僅導入模塊時,只會執行模塊的全局函數,不會導入任何成員。
示例:
// math.js export function add(a, b) { return a + b; } (function() { console.log('hello math.js'); })(); // app.js import { add } from './math.js'; // => hello math.js
4. 擴展閱讀
ECMAScript 6 modules: the final syntax :http://2ality.com/2014/09/es6-modules-final.html
MDN export :https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
MDN import:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
End Web開發之路系列文章 菜單載入中...