[toc]
由于歷史的原因,JavaScript沒有模塊(module)機制,而其他的語言比如Python(import),Ruby(require)等都支持模塊。這樣在實現比較大型復雜的項目時就遇到阻礙。不過在ES6之前,社區已經形成了一些模塊加載方案,比如CommonJS和AMD規范,并有相對成熟的庫。
ES6從語言層面實現了模塊功能,并且實現比較簡單,可以取代CommonJS和AMD規范,成為服務器和瀏覽器通用的模塊解決方案。
ES6的模塊設計思想是靜態化,也就是在編譯時就能確定模塊的依賴關系以及輸入輸出的變量。而CommonJS和AMD都是運行時才能確定。
比如在CommonJS中:
```
let {stat,exists,readFile} = require("fs")
//則會將fs模塊整體加載進來,然后只使用3個方法(運行時加載)
```
在ES6中:
```
import {stat,exits,readFile} from "fs"
//從fs模塊加載3個方法,其他方法不加載(編譯時加載)
```
在ES6中,模塊自動采用嚴格模式,無論有沒有使用'use strict',模塊功能主要有兩個命令:
- export
- import
## export命令
export命令用來規定模塊的對外接口.
一個模塊是一個獨立的文件,文件內部所有的變量外部都無法獲取。除非用export將其暴露出去。可以export一個變量,也可以export一個函數或類.
```
function v1(){...}
function v2(){...}
export {
v1 as fun1,
v2 as fun2
}
```
**as**關鍵字可以在export之前對變量名進行修改以對接口進行重命名
## import命令
import命令用來加載export暴露出的模塊接口。
```
import {v1,v2,v3} from "./m"
```
要將引入的變量使用大括號括起來,在引入其他模塊變量后也可以使用**as**進行重命名:
```
import {v1 as value} from "./m"
```
## 模塊的整體加載
如果模塊中有多個變量,又要全部加載的話,使用`*`表示:
```
import * from "./m"
```
## module命令
module命令可以取代import語句,達到整體輸入模塊的目的:
```
module m from "./m"
```
m模塊中的所有變量都可以通過m.xxx形式訪問
## export default命令
在上述例子中,使用import時都必須知道目標模塊中export的變量名,而使用export default則不需要,因為使用export default命令時,模塊內的變量名會被忽略。
export default命令可以將函數使用默認輸出,在其他模塊中引入時可以為函數其指定任意名字:
```
//m.js
export default function(){
console.log("foo");
}
---------
import fun1(任意指定) from "./m"
fun1(); //"foo"
```
## ES6模塊加載的實質
在CommonJS中,模塊的輸入是被輸出值的拷貝,也就是一旦輸出后,模塊內部的變化不會影響到這個值。而ES6的模塊運行機制不同,ES6的模塊import之后不回去執行模塊,而是會生成一個動態的只讀引用。當需要執行時候再去執行,如果模塊中的值變了,import之后的值也會變化。