ES6(ECMAScript 2015)引入了模塊化的概念,旨在使 JavaScript 更加模塊化、可維護和可重用。ES6 模塊允許我們在不同的文件中組織和管理代碼,使得不同模塊之間的依賴關系更加清晰。
1. 導出(Export)
1.1 命名導出(Named Exports)
命名導出允許你導出多個變量、函數或類,每個導出的名稱必須是唯一的。
// file1.js
export const name = 'John';
export function greet() {console.log('Hello!');
}
export class Person {constructor(name) {this.name = name;}
}
使用命名導出時,你可以在導入時使用相同的名稱來訪問這些導出。
// file2.js
import { name, greet, Person } from './file1';
console.log(name); // John
greet(); // Hello!
const person = new Person('Jane');
1.2 默認導出(Default Export)
每個模塊只能有一個默認導出。默認導出的語法更加簡潔,可以導出一個值(如對象、函數、類等)。
js// file1.js
const person = {name: 'John',age: 30
};
export default person;
導入默認導出的方式沒有花括號。
js// file2.js
import person from './file1';
console.log(person.name); // John
1.3 導出重命名(Export Rename)
你可以在導出時使用 as 進行重命名。
js// file1.js
const firstName = 'John';
export { firstName as name };
1.4 導出合并(Export All)
你可以一次性將一個模塊的所有導出重新導出,適用于模塊間的組合。
js
// file1.js
export const name = 'John';// file2.js
export * from './file1'; // 導出 file1.js 中所有的導出
2. 導入(Import)
2.1 導入命名導出(Named Imports)
// file1.js
export const name = 'John';
export function greet() {console.log('Hello!');
}// file2.js
import { name, greet } from './file1';
console.log(name); // John
greet(); // Hello!
2.2 導入默認導出(Default Import)
js
// file1.js
const person = { name: 'John' };
export default person;// file2.js
import person from './file1';
console.log(person.name); // John
2.3 導入重命名(Import Rename)
導入時使用 as 可以對導入的模塊進行重命名。
// file1.js
export const firstName = 'John';// file2.js
import { firstName as name } from './file1';
console.log(name); // John
2.4 導入全部(Import All)
你可以一次性導入一個模塊的所有命名導出,并將其作為一個對象使用。
// file1.js
export const name = 'John';
export const age = 30;// file2.js
import * as person from './file1';
console.log(person.name); // John
console.log(person.age); // 30
2.5 動態導入(Dynamic Import)
ES6 模塊支持動態導入,返回一個 Promise,可以根據需要異步加載模塊。
// 動態導入
import('./file1').then(module => {console.log(module.name);
});
3. 模塊化的特點
3.1 模塊是默認嚴格模式
ES6 模塊在模塊內部默認使用嚴格模式(‘use strict’;),因此所有模塊的代碼都是嚴格模式的代碼,不需要顯式聲明。
// file1.js
x = 10; // 報錯,嚴格模式下不允許未聲明的變量
3.2 模塊的作用域
每個模塊都有自己的作用域,不會污染全局作用域。模塊之間通過 import 和 export 進行通信。
// file1.js
let counter = 0;
export function increment() {counter++;
}// file2.js
import { increment } from './file1';
increment();
console.log(counter); // 由于作用域隔離,counter 在 file2.js 中不可訪問
3.3 循環依賴
ES6 模塊系統解決了模塊間的循環依賴問題。對于導入的模塊,它會暫時處于“掛起”狀態,直到依賴的模塊加載完成。
// a.js
import { b } from './b.js';
export const a = 'a';// b.js
import { a } from './a.js';
export const b = 'b';console.log(a, b); // 輸出: a b
3.4 只讀導入
ES6 模塊中的導入是只讀的。你無法修改從模塊導入的值。
// file1.js
export let name = 'John';// file2.js
import { name } from './file1';
name = 'Jane'; // 錯誤:不能修改從模塊導入的值
4. 使用模塊
4.1 模塊在瀏覽器中的使用
現代瀏覽器支持 module 類型的腳本。使用
<script type="module">import { name } from './file1.js';console.log(name);
</script>
4.2 在 Node.js 中使用 ES6 模塊
在 Node.js 中,你需要使用 .mjs 文件擴展名或在 package.json 中設置 “type”: “module”,來啟用 ES6 模塊。
{"type": "module"
}
然后,你就可以在 Node.js 中使用 import 和 export 語法了。
// file1.mjs
export const name = 'John';// file2.mjs
import { name } from './file1.mjs';
console.log(name); // John
5. 總結
ES6 模塊引入了更簡潔的語法,使得 JavaScript 的代碼結構更加清晰和可維護。通過 import 和 export,我們可以將代碼拆分成小的模塊,按需加載,并處理依賴關系。使用 ES6 模塊化的好處包括:
- 提高代碼的可維護性和可讀性。
- 更好的支持循環依賴。
- 默認嚴格模式,避免了許多常見的 JavaScript 問題。