ES6 Module
Module
當程式碼愈寫愈多,程式的規模愈來愈大時,需要一個管理程式碼的方式,而在 JavaScript 是一個沒有命名空間設計的程式語言,所以早在2003年社群中發展出模組樣式 (module pattern)
,不過它並沒有辦法徹底解決問題,後來在2009年之後開始發展出兩套真正完整的模組系統,就是 CommonJS 與 RequireJS (Asynchronous Module Definition 簡稱 AMD)。
CommonJS 是專門設計給伺服器端的 Node.js 使用,而 AMD 的目標對象則是瀏覽器端,這種方式可以同時間讀取所有引用和相依的模組,不像 CommonJS 所定義的規範是以同步的方式一個一個檔案的載入方式,確保所有相依模組的檔案都載入後才執行,所以 node js 也是採用 CommonJS 這規範。
一個好用的模組系統需包含幾項特點:程式中能載入模組, 模組間的相依性能管理, 異步載入模組, 大型專案一樣好管理。ES6 中加入了模組系統的支援,它採用了 CommonJS 與 AMD 的優點,是一個語言內建的模組系統,並且可以使用於瀏覽器與伺服器端。
CommonJS: require/module.exports
CommonJS 是為了解決 JavaScript 作用域問題而定的模組樣式,可以使每個模組自己本身的命名空間中執行。透過 module.exports
匯出對外的變數或函式,當要使用這模組到目前的作用域中,要用 require()
來導入外部模組。
// CommonJS 規範 module 這個字代表當前這個模組
var x = 5;
var addX = function (value) {
return value + x;
};
module.exports.x = x;
module.exports.addX = addX;
var example = require('./example.js');
console.log(example.x); // 5
console.log(example.addX(1)); // 6
module.exports 屬性表示當前模組對外的接口,實際上也是一個變數
var EventEmitter = require('events').EventEmitter;
module.exports = new EventEmitter();
setTimeout(function() {
module.exports.emit('ready');
}, 1000);
ES6 的模組系統
不論你在程式碼中有沒有使用 “use strict”, ES6 的模組程式碼會自動變成 strict-mode (嚴格模式)。
ES6 的模組是一個檔案一個模組
ES6 模組使用 export 與 import 來進行模組輸出與輸入。輸出通常位於檔案最後,輸入位於最前面。
單一輸出名稱
function aFunction(param){
return param * param
}
// 只會有一個輸出的變數/常數、函式、類別或物件,通常會加上 default
export default aFunction
// 單一輸出的模組就不需要用花括號,這代表只輸入以 default 值定義的輸出語句
import aFunction from './lib2.js'
console.log(aFunction(5))
// 單一輸出的模組,可以直接在輸入時改變輸入值的名稱
import square from './lib2.js'
console.log(square(5))
多個輸出名稱
export const aString = 'test'
export function aFunction(){
console.log('function test')
}
export const aObject = {a: 1}
export class aClass {
constructor(name, age){
this.name = name
this.age = age
}
}
// import 方法一,使用大括號,較常使用
import {aString, aObject, aFunction, aClass} from './lib.js'
console.log(aString)
console.log(aObject)
// import 方法二,使用萬用字元 * 並加上一個模組名稱 myModule 防止命名空間的衝突
import * as myModule from './lib.js'
console.log(myModule.aString)
console.log(myModule.aObject)
其他輸入的語法
import 'jquery'; // import a module without any import bindings
import $ from 'jquery'; // import the default export of a module
import { $ } from 'jquery'; // import a named export of a module
import { $ as jQuery } from 'jquery'; // import a named export to a different name
import * as crypto from 'crypto'; // import an entire module instance object
Ref
- https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part4/module_system.html
- http://stackoverflow.com/questions/36795819/react-native-es-6-when-should-i-use-curly-braces-for-import/36796281#36796281
- http://exploringjs.com/es6/ch_modules.html
- http://www.2ality.com/2014/09/es6-modules-final.html
- https://addyosmani.com/resources/essentialjsdesignpatterns/book/#modularjavascript
- https://www.nczonline.net/blog/2016/04/es6-module-loading-more-complicated-than-you-think/
Author Hello Jay
LastMod 2018-07-24