一、概述
之前提到的幾種模組化規範:CommonJS、AMD、CMD都是社群提出的。ES 2015在語言層面上實現了模組功能,且實現簡單,可以替代CommonJS和AMD規範,成為在伺服器和瀏覽器通用的解決方案
二、特性
1、ES Module自動啟用嚴格模式
<script type="module">
console.log(this); //undefined
</script>
2、ES Module執行在單獨的作用域中,與外界互不干擾
<script type="module">
var foo = 100;
console.log(foo);//100
</script>
<script type="module">
console.log(foo);//Uncaught ReferenceError: foo is not defined
</script>
3、ES Module是通過CORS方式請求外部檔案,需外部檔案支援CORS請求
//該檔案支援CORS請求,則可以請求成功
<script type="module" src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
//該檔案不支援CORS請求,報跨域錯誤
<script type="module" src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
4、ES Module引用的檔案會延遲執行
//index.js
alert('hello');
//index.html
<body>
<script type="module" src="./index.js"></script> 等價於 <script defer src="./index.js"></script>
<p>
文字內容
</p>
</body>
執行結果【js的載入並未影響到DOM的載入】
三、export命令
由於在ES Module中,每個模組都是一個單獨的作用域,如果想使模組內的變數暴露出去,使用export關鍵字,匯入其他模組的關鍵字使用import。
1、挨個匯出變數
//module.js
export var name = "張三";
export function add(a, b) {
return a + b;
}
export var obj = {
name: 'jack'
};
2、批量匯出變數
//module.js
var name = "張三";
function add(a, b) {
return a + b;
}
var obj = {
name: 'jack'
};
export { name, add, obj }
優點:在指令碼尾部,使用一個export統一匯出,清晰簡潔
3、匯出預設資料
//module.js
export default 'es module'
或者
export default function(a,b){
return a+b;
}
注意:說完import後再說注意事項
4、匯出時起別名,使用as關鍵字
//module.js
var name = "張三";
function add(a, b) {
return a + b;
}
var obj = {
name: 'jack'
};
export { name as v1, add as v2, obj as v3}
四、import命令
要想接受其他模組通過export匯出的成員時,使用import關鍵字
1、import匯入其他模組中的變數
//module.js
var name = "張三";
function add(a, b) {
return a + b;
}
export { name ,add }
//app.js
import { name, add as MathAdd} from "./module.js"
console.log(name);//張三
console.log(MathAdd(1, 1)) //2
注意:
1.1使用相對路徑 字尾名和./不能省略
import {name} from "./module.js"
1.2使用絕對路徑
import {name} from "/demo/module.js"
1.3使用全路徑
import {name} from "http://localhost:8080/demo/module.js"
1.4可以在匯入模組時使用as 起別名
起別名後,as前的變數不可使用了
2、使用import只執行引入檔案,不提取引入檔案中的成員時
- import {} from "./module.js";
- import './module.js'【常用】
//module.js
console.log('module.js中執行')
var name = "張三";
function add(a, b) {
return a + b;
}
var obj = {
name: 'jack'
};
export { name, add, obj }
//app.js
import {} from "./module.js";
或者寫成
import './module.js'
//index.html
<body>
<script type="module" src="./app.js"></script>
//執行結果
//module.js中執行
</body>
當多次執行同一個import語句時,只會執行一次
3、模組的整體載入
使用import除了可以載入單個值,也可以一次性載入模組匯出的所有值
//module.js
var name = "張三";
function add(a, b) {
return a + b;
}
var obj = {
name: 'jack'
};
export { name, add, obj }
//app.js
import * as all './module.js'
console.log('name:',all.name);
console.log('obj',all.obj);
console.log(add(1,1))
五、export default
前面使用export匯出模組內的成員時,需要指定具體的成員名稱,同樣載入時需要根據匯出的具體名稱進行載入。還有一種快捷的匯出方式,使用export default 為模組指定預設匯出,每個模組只能使用一次export default。
1、匯出匿名成員時,使用任意變數接受成員
//module.js
export default function(a, b) {
return a + b;
}
//app.js
import add from "./module.js";
console.log(add(1,2));
因為使用export匯出成員時是匿名的,所以在匯入時並不知道這個成員的名字是什麼,這時候就可以隨意寫變數去接受這個匿名成員,案例中使用add接受的匿名函式,也可以使用其他名稱接收。
注意:export default也可以匯出具名成員,但效果和匯出匿名成員是一樣的
//module.js
export default function add(a, b) {
return a + b;
}
//或者
function add(a,b){
return a + b;
}
export default add
//app.js
import temp from "./module.js";
console.log(temp(1,2));
總結:使用export default匯出成員,在外部載入時都視為匿名成員載入,可以隨意起變數名接受
2、同時匯入其他模組的預設成員和具名成員時
//module.js
var name = 'jack';
var age = 19;
export { name, age }
//匯出預設成員
export default 'default export'
//app.js
import str,{name,age} from "./module.js";
或者
import {name,age,default as str} from "./module.js"
console.log(str);//default export
console.log(name);//jack
console.log(age);//19
3、另類的預設匯出
//module.js
var number = 1;
export { number as default }
等同於
export default number;
//app.js
import { default as number} from "./module.js"
console.log(number); //1
總結:可見export default的本質就是匯出一個名字叫default的成員,當匯出的成員叫default時,接受這個成員可以隨意命名
4、使用export default來匯出類
//Person.js
export default class Person(){
....
}
//main.js
import Person from "./Person.js";
const person = new Person();
5、比較一下預設輸出和正常輸出
//1.預設輸出
export default function add(a,b){
return a + b;
}
//接受預設輸出
import temp from './module.js'
//2.具名輸出
function add (a,b){
return a + b;
}
export {add}
//接受具名輸出
import {add} from './module.js'
總結:使用預設匯出時,在外部接受成員,不需要使用大括號;使用具名輸出時,在外部接受成員時,import後需要使用大括號
六、迷惑性的點
1、export批量匯出變數時,匯出的並不是物件字面量
//module.js
var name = 'jack';
var age = 19;
export { name, age }
//export {name,age} 並不是匯出的一個物件,而是export批量匯出的語法
2、import載入多個變數時,並不是ES6的解構用法
import {name,age} from "./module.js"
//impot後面的大括號並不是解構作用
3、import匯入的變數都是常量,不可修改,與CommonJS不同
七、export和import的複合用法
當我們在檔案內import一個成員後,同時把它匯出時
//index.js
import {Button} from './button.js'
export { Button }
可以寫成
export {Button} from "./button.js"
八、import()函式
import關鍵字匯入其他模組成員時,必須寫在最頂層作用域,不可巢狀在其他邏輯處理中。如果說我們想在某段邏輯執行完成後去動態載入某些成員,這時候可以使用import()函式載入
//module.js
var name = "張三";
function add(a, b) {
return a + b;
}
var obj = {
name: 'jack'
};
export { name, add, obj }
export default function() {
return '匿名成員'
}
//app.js
//使用setTimeout來模擬一個非同步載入的過程
setTimeout(() => {
//import返回的是個promise,返回的模組內容都在回撥函式的引數中(moduleResult)
import ("./module.js").then(moduleResult => {
console.log(moduleResult)
console.log(moduleResult.add)
console.log(moduleResult.name)
console.log(moduleResult.default)
console.log(moduleResult.obj)
})
//也可以直接把成員結構出來
import ("./module.js").then(({add,name,obj,default:defaultData}}) => {
console.log(moduleResult.add)
console.log(moduleResult.name)
console.log(moduleResult.defaultData)
console.log(moduleResult.obj)
})
}, 2000);