JS 中 export/import 關鍵詞的使用指南
在 JavaScript 模塊化開發中,export和import是一對不可或缺的關鍵詞。它們解決了代碼拆分、複用和作用域隔離的問題,讓開發者能夠將複雜項目拆分成多個獨立文件,每個文件專注於特定功能,再通過這對關鍵詞實現文件間的代碼共享。無論是瀏覽器端開發還是 Node.js 環境,export/import都已成為模塊化開發的標準方案,讓代碼結構更清晰、維護更便捷。
export關鍵詞的作用是將當前文件中的變量、函數、類等成員暴露出去,供其他文件導入使用。它主要有兩種使用方式:命名導出和默認導出,兩種方式可以根據實際需求靈活選擇。
命名導出允許在一個文件中暴露多個成員,每個成員都有自己的名稱,導入時需要使用對應的名稱接收。命名導出的語法既可以在聲明時直接添加export,也可以在文件末尾集中導出。
命名導出代碼示例:
// 方式一:聲明時直接導出
export const PI = 3.14159;
export function calculateArea(radius) {
return PI * radius * radius;
}
export class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, I'm ${this.name}`);
}
}
// 方式二:末尾集中導出(適合批量暴露多個成員)
const maxNum = 100;
function formatDate(date) {
return date.toLocaleDateString();
}
export { maxNum, formatDate };
// 導出時重命名(解決名稱衝突問題)
export { formatDate as formatLocalDate };
默認導出則用於一個文件中暴露唯一的核心成員,每個文件只能有一個默認導出。默認導出的成員在導入時可以自由命名,無需與導出時的名稱一致,這讓導入語法更靈活。
默認導出代碼示例:
// 方式一:直接導出默認成員
export default function add(a, b) {
return a + b;
}
// 方式二:先聲明後導出默認成員
const multiply = (x, y) => x * y;
export default multiply;
// 類的默認導出
class MathUtil {
static subtract(a, b) {
return a - b;
}
}
export default MathUtil;
// 注意:一個文件只能有一個默認導出,以下寫法報錯
export default const num = 10;
export default function minus() {} // 報錯:SyntaxError: Duplicate export of 'default'
import關鍵詞用於導入其他文件通過export暴露的成員,它的語法需要與導出方式對應。導入命名導出的成員時,需要使用花括號{}包裹成員名稱,且名稱必須與導出時一致(除非使用重命名);導入默認導出的成員時,無需使用花括號,可以直接自定義名稱。
基礎導入代碼示例:
// 導入命名導出的成員
import { PI, calculateArea, Person } from './mathModule.js';
console.log(PI); // 輸出:3.14159
console.log(calculateArea(5)); // 輸出:78.53975
const person = new Person('張三', 25);
person.sayHello(); // 輸出:Hello, I'm 張三
// 導入時重命名(避免名稱衝突)
import { maxNum as maxLimit, formatLocalDate } from './mathModule.js';
console.log(maxLimit); // 輸出:100
console.log(formatLocalDate(new Date())); // 輸出當前本地日期
// 導入默認導出的成員(自定義名稱)
import addFunc from './mathModule.js';
console.log(addFunc(3, 5)); // 輸出:8
// 導入默認導出和命名導出的混合寫法
import MathUtil, { PI } from './mathModule.js';
console.log(MathUtil.subtract(10, 3)); // 輸出:7
console.log(PI); // 輸出:3.14159
除了指定導入特定成員,還可以使用整體導入的方式,將一個模塊的所有暴露成員導入為一個對象,通過對象屬性訪問各個成員。這種方式適合導入多個成員但不想逐個列舉的場景,也能避免名稱衝突。
整體導入代碼示例:
// 整體導入:將所有暴露成員掛載到mathObj對象上
import * as mathObj from './mathModule.js';
console.log(mathObj.PI); // 輸出:3.14159
console.log(mathObj.calculateArea(4)); // 輸出:50.26544
const p = new mathObj.Person('李四', 30);
p.sayHello(); // 輸出:Hello, I'm 李四
console.log(mathObj.default(2, 4)); // 輸出:6(訪問默認導出的成員)
在實際開發中,export/import還有一些實用的細節需要注意。比如導入路徑可以是相對路徑(./、../開頭),也可以是絕對路徑或第三方模塊名稱(如 Node.js 中的lodash);模塊導入是靜態的,只能在文件頂部導入,不能在函數、條件語句等代碼塊中動態導入(如需動態導入,可使用import()函數);此外,導出的成員是只讀的,導入後不能修改其值(引用類型的屬性可以修改,但不建議這樣做,會破壞模塊的封裝性)。
常見注意事項代碼示例:
// 1. 導入路徑示例
import { formatDate } from './utils/date.js'; // 相對路徑
import lodash from 'lodash'; // 第三方模塊
// 2. 靜態導入限制:以下寫法報錯
if (true) {
import { PI } from './mathModule.js'; // 報錯:SyntaxError: Unexpected token 'import'
}
// 3. 導入的成員只讀
import { PI, user } from './mathModule.js';
PI = 3.14; // 報錯:TypeError: Assignment to constant variable
user.name = '王五'; // 不報錯(引用類型屬性可修改,但不推薦)
export/import的出現徹底改變了 JavaScript 的模塊化開發方式,替代了過去的 CommonJS(require/module.exports)和 AMD 規範,成為 ES6 及以後的標準模塊化方案。在實際項目中,合理使用export/import可以將代碼拆分成職責單一的模塊,提高代碼複用率和可維護性,同時讓依賴關係更清晰,便於團隊協作開發。無論是開發小型工具庫,還是大型前端應用,export/import都是必須熟練掌握的核心關鍵詞。