- ESM 預設嚴格模式:無論有沒有使用 'use strict',都會自動變成 'use strict'。
- 作用域獨立:每個模組都是獨立作用域,也就是
<script type="module"></script>
都擁有一個自己的空間,不可以跨域去取值。
<!-- 沒有模組化的 <script>,可以從另一個 <script> 順利取到已宣告的變數的值 -->
<script>
let sayHi = 'hi';
</script>
<script>
console.log(sayHi); // hi
</script>
<!-- 寫成 <script type="module"> 時,
就無法從另一個 <script> 取到 <script type="module"> 已宣告的變數的值 -->
<script type="module">
let sayHi = 'hi';
</script>
<script>
console.log(sayHi); // Uncaught ReferenceError: sayHi is not defined
</script>
運作
在使用 ESM 的 <script>
加上 type="module"
。
<script type="module"></script>
Export 匯出
export
可以匯出物件、函式和純值。分為兩種,根據匯出的形式不同,會影響 import
時的寫法:
預設匯出(default export):
- 在匯出時沒有給予特定名稱。
- 一個檔案裡面只能有一個 default export。
- 在實作開發時常用到。
// 直接匯出純值
export default 1;
// 代入變數
const a = 1;
export default a;
// 匯出物件
const obj1 = {person: 'Tom'};
export default obj1;
// 匯出多個物件
const obj1 = {person: 'Tom'};
const obj2 = {person: 'Mary'};
export default {obj1, obj2}; // 使用物件縮寫(Object shorthand)形式匯出
預設匯出(default export)可以直接匯出匿名函式。
export default function(){
console.log('Hi, I\'m function');
};
具名匯出(named export):
- 在匯出時會給予特定名稱,並在匯入時代入該名稱匯入。
- 一個檔案裡面可以有多個 named export。
- 常使用在函式庫。
在
export
後緊接使用let
,const
宣告後再匯出。export let a = 1; export const obj1 = {person: 'Tom'};
使用函式陳述式匯出
export function sayHi(){ console.log('hi'); };
使用物件縮寫(Object shorthand)形式匯出
```javascript=
let a = 1;
const obj1 = {person: 'Tom'};
const obj2 = {person: 'Mary'};
export {a, obj1, obj2};
匯出前可以使用 `as` 修改名稱。
```javascript=
const obj = {dog: 'kuro'};
export {obj as newObj};
Import 匯入
匯入 預設匯出(default export)
預設匯出因為在匯出時沒有賦予名稱,所以匯入時要賦予一個名稱。
// export file
export default function(){
console.log('Hi, I\'m function');
};
// import file
// import 要賦予的名稱 form '檔案位置(html 要加上 .js)';
import fn form './js/esm.js';
匯入 具名匯出(named export)
- 需要使用物件解構的方式將特定模組取出,並且模組名稱需要一致。
// export file
function fn(){
console.log('Hi, I\'m function');
};
const obj = {dog: 'kuro'};
export {fn, obj};
// import file
import {fn, obj} form './js/esm.js';
fn(); // 'Hi, I'm function'
console.log(obj); // {dog: 'kuro'}
- 在匯入時也可以和匯出時一樣將模組重新命名。
// export file
export function fn(){
console.log('Hi, I\'m function');
};
// import file
import {fn as newFn} form './js/esm.js';
newFn(); // 'Hi, I'm function'
- 也可以使用
*
全部匯入。此時需要使用as
指向一個新物件變數,此物件內容就是匯出的所有模組。
// export file
function fn(){
console.log('Hi, I\'m function');
};
const obj = {dog: 'kuro'};
export {fn, obj};
// import file
import * as allObj form './js/esm.js';
allObj.fn();
console.log(allObj.obj);
同時匯入 預設匯出(default export)、具名匯出(named export)
// export file
export default function (){
console.log('Hi, I\'m function');
};
export const obj = {dog: 'kuro'};
// import file
// 為預設匯出賦予名稱 fn,將所有具名匯出指向到新的物件 allObj
import fn, * as allObj form './js/esm.js';
fn();
console.log(allObj.obj);
Side Effect 模組
有些模組沒有使用 export,例如可以直接執行的 IIFE,不需要另外呼叫就可以直接執行可稱為 Side Effect 模組。
常見案例有早期版本的框架,直接將方法綁定在 window,不需要呼叫即可運作,例如:jQuery
, angularJs
。
// 不需要進行匯出,可以直接用 import 匯入運作
(function(){
console.log('hi');
})();
//import file
import '檔案位置.js'; // hi
// jQuery.js 範例
(function(global){
global.$ = {
sayHello() {
console.log('Hello, world');
},
myName: 'world',
obj: {
myName: 'world',
},
arr: [1, 2, 3],
}
})(window);
/* app.js */
console.log($.myName); // 'world'
$.sayHello(); // Hello, World
console.log($.obj.myName); // world'
console.log($.arr[0]); // 1