ES6 模块(ES Modules)

ES6 模块(ES Modules,简称 ESM)是 JavaScript 的官方模块系统,使用 importexport 语法。


📚 基本语法

export 导出

命名导出(Named Export)

// math.js
export const PI = 3.14159;
export function add(a, b) {
  return a + b;
}
export class Calculator {
  multiply(a, b) {
    return a * b;
  }
}
 
// 或者先定义后导出
const PI = 3.14159;
function add(a, b) {
  return a + b;
}
export { PI, add };

默认导出(Default Export)

// utils.js
export default function formatDate(date) {
  return date.toISOString();
}
 
// 或者
function formatDate(date) {
  return date.toISOString();
}
export default formatDate;

混合导出

// config.js
export const API_URL = 'https://api.example.com';
export default {
  timeout: 5000,
  retries: 3
};

import 导入

命名导入

// 导入单个
import { PI, add } from './math.js';
 
// 导入全部
import * as math from './math.js';
console.log(math.PI);
console.log(math.add(1, 2));
 
// 重命名导入
import { add as sum } from './math.js';

默认导入

import formatDate from './utils.js';
 
// 默认导入和命名导入混合
import formatDate, { API_URL } from './config.js';

仅执行模块(不导入任何内容)

import './polyfills.js'; // 执行模块,但不导入任何内容

🔍 特性

1. 静态分析

ES6 模块在编译时就能确定导入导出关系,支持:

  • 静态分析
  • Tree shaking(死代码消除)
  • 更好的 IDE 支持
// 编译时就能确定导入关系
import { add } from './math.js'; // ✅ 静态导入
 
// 动态导入需要使用 import()
const module = await import('./math.js'); // 动态导入

2. 严格模式

ES6 模块自动启用严格模式:

// 无需 'use strict'
export function test() {
  x = 10; // ❌ 报错:x is not defined(严格模式)
}

3. 顶层 this

ES6 模块中,顶层 thisundefined

console.log(this); // undefined(在模块中)

4. 单次执行

模块只执行一次,多次导入会共享同一个模块实例:

// counter.js
let count = 0;
export function increment() {
  count++;
  return count;
}
 
// a.js
import { increment } from './counter.js';
increment(); // 1
 
// b.js
import { increment } from './counter.js';
increment(); // 2(共享同一个 count)

📦 模块路径

相对路径

import { add } from './math.js';        // 当前目录
import { utils } from '../utils.js';    // 上级目录
import { config } from './config/index.js'; // 子目录

绝对路径(需要配置)

// 需要配置路径别名(如 webpack、vite 等)
import { utils } from '@/utils/index.js';

包导入

import React from 'react';
import { debounce } from 'lodash';

🔄 与 CommonJS 对比

特性ES6 模块CommonJS
加载时机编译时运行时
导出方式exportmodule.exports
导入方式importrequire
默认导出export defaultmodule.exports =
命名导出export { name }exports.name =
动态导入import()require()
顶层 thisundefinedmodule

💡 最佳实践

1. 文件扩展名

// ✅ 推荐:明确指定 .js 扩展名
import { add } from './math.js';
 
// ⚠️ 某些环境可以不写,但不推荐
import { add } from './math';

2. 导出方式选择

// ✅ 推荐:使用命名导出(更明确)
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }
 
// ⚠️ 默认导出用于单一主要功能
export default class Calculator { }

3. 导入顺序

// ✅ 推荐顺序:外部库 → 内部模块 → 相对路径
import React from 'react';
import { utils } from '@/utils';
import { add } from './math.js';

4. 避免循环依赖

// ❌ 避免循环依赖
// a.js
import { b } from './b.js';
export const a = 'a';
 
// b.js
import { a } from './a.js'; // 可能导致问题
export const b = 'b';

🔗 相关链接


参考


javascript 模块化 es-modules es6