模块化体系

1.7 模块化体系

模块化是现代前端工程化的核心基石,通过将代码拆分为独立、可复用的模块,实现作用域隔离、依赖管理、按需加载与代码复用。

ES6 推出的 ES Modules(ESM)是 JavaScript 官方标准化的模块化方案,统一了早期 CommonJS、AMD 等多种社区规范,是当前前端开发的标准模块化方式,也是构建工具、框架生态的底层基础。


1.7.1 ES Modules:import /export 标准语法

ES Modules 基于 import 和 export 关键字实现模块的导入与导出,模块文件自动拥有独立作用域,只有显式导出的成员才能被外部访问。

一、export 导出语法

导出分为命名导出 和默认导出两种形式,支持单个导出、批量导出、重命名导出与聚合导出。

  1. 命名导出
  2. 一个模块可以有多个命名导出,导入时需与导出名严格对应。
javascript 复制代码
// 单个声明时直接导出
export const baseURL = 'https://api.example.com';
export function formatDate(date) {
  return date.toISOString().slice(0, 10);
}
export class User {
  constructor(name) {
    this.name = name;
  }
}

// 声明后统一批量导出
const version = '1.0.0';
function log(msg) {
  console.log(msg);
}
export { version, log };
  1. 重命名导出
  2. 通过 as 关键字修改导出的对外名称。
javascript 复制代码
const innerFn = () => {};
export { innerFn as publicFn };
  1. 默认导出
  2. 一个模块只能有一个默认导出,对应一个默认值,适合导出单个核心成员(如单个类、单个函数)。
javascript 复制代码
// 导出函数
export default function add(a, b) {
  return a + b;
}

// 导出对象
export default {
  name: 'utils',
  version: '1.0.0'
};
  1. 聚合导出(中转导出)
  2. 在入口模块中统一转发其他模块的导出,简化外部引用路径。
javascript 复制代码
// 转发所有命名导出
export * from './utils.js';
// 转发并重命名
export { default as DateUtil } from './date.js';
二、import 导入语法

对应导出语法,导入分为命名导入、默认导入、整体导入与重命名导入。

  1. 命名导入
  2. 使用花括号包裹,导入名必须与导出名完全一致。
javascript 复制代码
import { baseURL, formatDate } from './config.js';
console.log(baseURL);
  1. 重命名导入
  2. 通过 as 修改导入后的变量名,解决命名冲突问题。
javascript 复制代码
import { formatDate as format } from './config.js';
  1. 默认导入
  2. 无需花括号,可自定义导入名称。
javascript 复制代码
import add from './add.js';
console.log(add(1, 2));
  1. 整体命名空间导入
  2. 通过 * as 将模块所有命名导出挂载到一个对象上。
javascript 复制代码
import * as utils from './utils.js';
console.log(utils.version);
utils.log('test');
三、基础语法约束
  • import / export 只能出现在模块顶层作用域,不能嵌套在函数、条件语句等块级作用域中
  • 模块路径支持相对路径与绝对路径,省略后缀时需构建工具支持
  • 导入的变量是只读引用,不可在导入侧直接修改导出值

1.7.2 动态 import () 按需加载

静态 import 语法必须在模块顶层执行,无法实现条件加载与按需加载。ES2020 引入的动态 import() 以函数形式调用,返回一个 Promise 对象,可在任意时机动态加载模块,是性能优化的核心手段。

一、基础语法
javascript 复制代码
import(modulePath)
  .then(module => {
    // module 为模块导出对象
    module.default();
  })
  .catch(err => {
    console.error('模块加载失败:', err);
  });

配合 async/await 使用更简洁:

javascript 复制代码
async function loadModule() {
  try {
    const utils = await import('./utils.js');
    utils.doSomething();
  } catch (err) {
    console.error('加载失败', err);
  }
}
二、典型应用场景
  1. 条件加载:根据运行环境、特性支持度按需加载模块
javascript 复制代码
if (!window.IntersectionObserver) {
  await import('./intersection-polyfill.js');
}
  1. 交互触发加载:用户触发特定操作时再加载对应功能模块,降低首屏体积
javascript 复制代码
// 点击按钮后再加载弹窗模块
modalBtn.addEventListener('click', async () => {
  const Modal = (await import('./Modal.js')).default;
  new Modal().show();
});
  1. 路由懒加载:单页应用中按路由拆分代码,进入对应页面时才加载页面资源
  2. 大依赖延迟加载:体积较大的第三方库(如图表、富文本编辑器)在使用前再加载

1.7.3 模块作用域与依赖机制

ES Modules 拥有独立的作用域与明确的依赖执行规则,从语法层面解决了全局变量污染、依赖顺序混乱等问题。

一、模块作用域

每个 ES Module 都拥有独立的私有作用域:

  • 模块内声明的变量、函数、类默认仅在模块内部可见,不会泄露到全局作用域
  • 只有通过 export 显式导出的成员,才能被外部模块访问
  • 不同模块之间的同名变量不会互相冲突

对比传统脚本文件:多个普通 script 标签共享全局作用域,容易出现变量覆盖、命名冲突;模块文件天然隔离,无需手动封装闭包。

二、单例与引用机制
  • 单例执行:同一个模块被多次导入时,仅会在第一次导入时执行一次模块代码,后续导入直接复用导出结果,不会重复执行
  • 值的引用:导入的是导出值的引用,而非值的拷贝。若模块内部修改了导出的变量,所有导入该模块的地方都会同步更新
javascript 复制代码
// counter.js
export let count = 0;
export function increment() {
  count++;
}

// a.js
import { count, increment } from './counter.js';
increment();
console.log(count); // 1

// b.js
import { count } from './counter.js';
console.log(count); // 1,与 a.js 共享同一份引用
三、依赖执行规则

模块按照依赖树深度优先的顺序执行:

  1. 先执行当前模块的所有依赖模块,再执行当前模块自身代码
  2. 循环依赖场景下,已执行的部分会正常导出,未执行的部分为 undefined,需避免复杂循环依赖
四、默认严格模式

所有 ES Module 自动运行在严格模式下,无需手动声明 'use strict',因此模块内默认遵循严格模式的所有约束(如禁止未声明变量赋值、禁止 with 语句等)。

相关推荐
小poop6 小时前
CSS 基础与实战:从入门到精通网页美化
前端
Csvn8 小时前
运行时性能
前端
Never_every999 小时前
位图转矢量工具哪个好?实测抠抠图AI位图转矢量工具
大数据·前端
paopaokaka_luck9 小时前
宠物门店经营管理系统(销售与库存联动、进货自动记账、 退换与退款关联、员工个人业绩、ECharts 经营分析、滞销识别与客户分层、宠物档案年龄计算)
前端·javascript·spring boot·mysql·echarts·mybatis·1024程序员节
空中湖10 小时前
用 React 写数据大屏:为什么我不建议用图表库
前端·react.js·前端框架
欣欣之王来了11 小时前
原始HTML插值:v-html指令的使用与安全风险
前端·学习·架构·项目·vue3教程
IT_陈寒11 小时前
Redis的LRU淘汰策略坑了我一整天
前端·人工智能·后端
计算机魔术师11 小时前
砍半价格、参数再涨,国产旗舰追到 Opus 鼻尖了
前端
特立独行的猫A12 小时前
10 MB 的桌面 AI 客户端:用仓颉 + 系统 WebView 替代 Electron
前端·harmonyos
修炼的dance12 小时前
白底图存JPG,sharp开mozjpeg背景杂点少近三成
前端