📦 第九章:模块化系统

掌握现代 JavaScript 的模块系统

9.1 ES Modules vs CommonJS

特性 ES Modules CommonJS
语法 import / export require() / module.exports
加载方式 静态加载(编译时) 动态加载(运行时)
支持环境 浏览器、Node.js 12+ Node.js
默认行为 严格模式 非严格模式
循环依赖 处理更优雅 可能导致问题

ES Modules 示例

// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export default {
    add,
    subtract
};

// app.js
import math from './math.js';
import { add, subtract } from './math.js';

console.log(math.add(1, 2)); // 3
console.log(add(3, 4)); // 7

CommonJS 示例

// math.js
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;

module.exports = {
    add,
    subtract
};

// app.js
const math = require('./math.js');

console.log(math.add(1, 2)); // 3

9.2 默认导出 vs 命名导出

默认导出

// 默认导出
export default function() {
    return 'Hello';
};

// 或
const myFunction = function() {
    return 'Hello';
};
export default myFunction;

// 导入
import myFunction from './module.js';

命名导出

// 命名导出
export const PI = 3.14159;
export function add(a, b) {
    return a + b;
};

// 或
const PI = 3.14159;
function add(a, b) {
    return a + b;
};
export { PI, add };

// 导入
import { PI, add } from './module.js';
import * as math from './module.js';

9.3 动态导入与代码分割

动态导入允许在运行时按需加载模块,实现代码分割,提高应用性能。
// 动态导入
async function loadModule() {
    const module = await import('./module.js');
    return module.default();
}

// 条件导入
async function loadFeature(feature) {
    switch (feature) {
        case 'math':
            const math = await import('./math.js');
            return math.add(1, 2);
        case 'string':
            const string = await import('./string.js');
            return string.capitalize('hello');
        default:
            throw new Error('Unknown feature');
    }
}

9.4 ES2026 新特性:导入属性与 JSON 模块

导入属性

// 导入属性
import data from './data.json' with { type: 'json' };

console.log(data); // 解析后的 JSON 对象

JSON 模块原生支持

// data.json
{
    "name": "John",
    "age": 30,
    "city": "New York"
}

// app.js
import data from './data.json' with { type: 'json' };

console.log(data.name); // John

9.5 ES2026 新特性:import defer 与 import source

import defer

// 延迟导入
import defer * as math from './math.js';

// 模块会在需要时加载
async function calculate() {
    const result = await math.add(1, 2);
    console.log(result);
}

import source

// 导入源
import source from './module.js';

// source 包含模块的源代码
console.log(source); // 模块的源代码字符串

动手练习

练习 1:ES Modules 基本使用

  1. 创建一个模块文件
  2. 导出一些函数和变量
  3. 在另一个文件中导入并使用

练习 2:默认导出与命名导出

  1. 创建默认导出
  2. 创建命名导出
  3. 测试不同的导入方式

练习 3:动态导入

  1. 使用动态导入加载模块
  2. 实现条件导入
  3. 测试代码分割效果

练习 4:ES2026 新特性

  1. 使用导入属性加载 JSON
  2. 测试 import defer
  3. 测试 import source