news 2026/2/20 17:48:50

深入浅出 ES Module

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入浅出 ES Module

概述

在 JavaScript 模块化发展历程中,为解决全局变量污染,代码依赖管理等问题,先后出现了 CommonJS(CJS)、AMD、CMD、UMD、ES6 Module(ESM)五大主流方案。不同方案因设计目标、运行环境(浏览器 / Node)的差异,形成了各自的语法特性与生态定位。

其中ES6 Module是 ES6 官方定义的标准化模块化方案,旨在统一浏览器与服务器端的模块化语法,解决传统模块化方案(如 CommonJS、AMD)的碎片化问题。

核心特性

静态化设计:模块的导入(import)与导出(export)声明必须在模块顶层,且导入导出的模块标识符(如文件路径)需是静态字符串,不能动态拼接(如 ·import('./' + path)· 是不允许的)。这一特性让 JavaScript 引擎在编译阶段就能分析模块依赖关系,实现 Tree-Shaking(摇树优化,剔除未使用的代码)。

独立模块作用域:每个 ESM 模块都是一个独立的作用域,模块内声明的变量、函数、类默认不对外暴露,需通过export显式导出后,其他模块才能通过import导入使用,这样可以避免全局变量污染。

值引用特性:ESM 导入的模块成员是 “值的引用”(而非 CommonJS 的值的拷贝),若导出模块修改了导出的变量(如导出一个 let 声明的变量并后续修改),导入模块会同步感知到变化(需注意:基础类型值若用const声明,因不可修改,不会有此特性)。

异步加载:在浏览器环境中,ESM 默认通过 <script type="module"> 标签异步加载(相当于给 <script> 加了defer属性),不会阻塞 HTML 解析,且模块加载完成后会按依赖顺序执行。

基础语法

导出(export)

命名导出:导出多个独立的模块成员,导入时需用相同的名称接收(可通过as重命名);

默认导出:每个模块最多只能有一个默认导出,导入时可自定义接收名称(无需加大括号)。

// 模块A:moduleA.js

// 1. 命名导出(方式1:声明时导出)

export const name = 'ES6 Module';

export function add(a, b) {

return a + b;

}

// 2. 命名导出(方式2:集中导出)

const age = 6;

const multiply = (a, b) => a * b;

export { age, multiply as multiplyFn }; // as重命名导出

// 3. 默认导出(方式1:直接导出)

export default class ModuleClass {

constructor() {

this.version = '1.0.0';

}

}

// 4. 默认导出(方式2:先声明后导出)

const defaultObj = { type: 'module' };

export default defaultObj;

导入语法(import)

导入命名成员:需用大括号包裹导入的成员名称,与导出名称一致(可通过as重命名);

导入默认成员:无需大括号,可自定义接收名称;

整体导入:用 * as 模块名 导入整个模块的所有导出成员,访问时需通过 模块名.成员名 的方式;

导入执行:若导入模块仅需执行其代码(如执行初始化逻辑,无需使用其导出成员),可直接使用 import './moduleA.js'。'

// 模块B:moduleB.js

// 1. 导入命名成员(原样接收)

import { name, add } from './moduleA.js';

console.log(name); // 输出:ES6 Module

console.log(add(2, 3)); // 输出:5

// 2. 导入命名成员(重命名接收)

import { age, multiplyFn as multiply } from './moduleA.js';

console.log(age); // 输出:6

console.log(multiply(2, 3)); // 输出:6

// 3. 导入默认成员(自定义名称)

import ModuleClass from './moduleA.js'; // 无需大括号

const instance = new ModuleClass();

console.log(instance.version); // 输出:1.0.0

// 4. 混合导入(命名成员+默认成员)

import ModuleClass, { name as moduleName } from './moduleA.js';

console.log(moduleName); // 输出:ES6 Module

// 5. 整体导入

import * as ModuleA from './moduleA.js';

console.log(ModuleA.name); // 输出:ES6 Module

console.log(ModuleA.add(2, 3)); // 输出:5

console.log(new ModuleA.default().version); // 输出:1.0.0(默认成员需通过.default访问)

// 6. 导入执行

import './moduleA.js'; // 仅执行moduleA.js的代码,不使用其导出成员

模块方案对比

CJS(CommonJS)

Node.js 原生支持的模块化方案,面向服务端,采用运行时动态加载,通过require导入、module.exports导出;

设计目标

◦ 解决 Node.js 服务端模块依赖管理问题,避免全局变量污染;

◦ 基于文件即模块理念,每个文件是独立模块,通过module.exports暴露成员,require加载模块。

特点

运行时加载:运行时动态加载,代码执行到require语句时,才会读取目标文件、执行模块代码、返回module.exports对象;

值传递:基础类型是值的拷贝, 对象类型则是引用传递,require时会将module.exports的属性值拷贝,后续导出模块修改基础类型值,导入模块不会同步变化;

缓存模块:模块首次加载后,会缓存module.exports对象,后续require同一模块时,直接返回缓存结果,避免重复执行模块代码;

运行环境:主要用于 Node.js,浏览器端需通过 Browserify、Webpack 等工具转换为全局变量或 ESM。

AMD(Asynchronous Module Definition)

面向浏览器端的异步模块化方案,解决浏览器加载模块时 “阻塞页面渲染” 问题,代表实现为 RequireJS;

设计目标

解决浏览器端同步加载模块阻塞页面渲染问题,通过异步方式加载模块,加载完成后执行回调函数;

支持依赖前置(提前声明所有依赖),确保模块执行时依赖已加载完成。

特点

异步加载: 通过 <script> 标签动态创建请求加载模块,加载完成后触发回调函数,不阻塞 HTML 解析与页面渲染;

依赖前置:模块定义时需提前声明所有依赖,如define(['jquery'], ...),RequireJS 会先加载依赖模块,所有依赖加载完成后,再执行当前模块的工厂函数;

运行环境:仅支持浏览器端,Node 端需通过amd-loader等工具转换;

支持多种路径写法:支持相对路径(如./moduleA)、绝对路径(如/js/moduleA)、模块别名(如jquery)。

UMD(Universal Module Definition)

通用模块定义,兼容 ESM、CJS、AMD 三种方案,可在浏览器与 Node 端通用,主要用于第三方库发布。

设计目标

◦ 解决第三方库需适配多模块方案的问题,使用一套代码就能够同时兼容 ESM、CJS、AMD 三种方案,可在浏览器与 Node 端通用,避免为不同模块方案单独发布代码,降低维护成本。

特点

多环境适配:可在Node和浏览器端使用,检测方式为 typeof define === 'function' && define.amd 检测 AMD 环境,typeof module === 'object' && module.exports 检测 CJS 环境,否则降级为全局变量;

ESM(ES6 Module)

ES6 官方标准化方案,兼顾浏览器与 Node 端,采用编译时静态加载,支持 Tree-Shaking,通过 import/export 语法实现。

设计目标

ES6 官方统一浏览器与 Node 端的模块化方案,解决传统方案碎片化问题;

基于编译时静态加载设计,支持 Tree-Shaking。

特点

编译时静态加载:JavaScript 引擎在编译阶段分析模块依赖,构建依赖树,不执行模块代码,因为是静态编译的时候做了分析,所以很自然的支持 Tree Shaking。

值的引用传递:导入的成员是对导出模块成员的引用,若导出模块修改非const变量,导入模块会同步变化。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/19 0:57:20

BERT微调实践:冻结预训练层+分类头增量训练详解

本文通过一个完整的情感分析二分类任务&#xff0c;详细讲解如何使用BERT进行模型微调&#xff08;Fine-tuning&#xff09;&#xff0c;重点分析冻结预训练参数和增量训练分类头的核心思想与实现细节。一、完整代码实现# net.py # -*- coding: utf-8 -*- """ B…

作者头像 李华
网站建设 2026/2/12 6:30:00

单芯片音频二分频新高度:全系列高通QCC平台智能分频方案解析

单芯片音频二分频新高度&#xff1a;全系列高通QCC平台智能分频方案解析 腾泰技术再次突破音频处理技术瓶颈&#xff0c;基于对高通QCC平台DSP核心的深度驾驭与算法创新&#xff0c;在全系列芯片上实现了单芯片高品质音频二分频硬件方案&#xff0c;为多扬声器音频设备带来集成…

作者头像 李华
网站建设 2026/2/17 17:20:48

FilamentPHP 3.3.15版本发布:表单构建革命与性能飞跃

FilamentPHP 3.3.15版本发布&#xff1a;表单构建革命与性能飞跃 【免费下载链接】filament filament&#xff1a;这是一个基于Laravel框架的模块化CMS系统&#xff0c;适合搭建企业级网站和应用程序。特点包括模块化设计、易于扩展、支持多语言等。 项目地址: https://gitco…

作者头像 李华
网站建设 2026/2/5 14:14:51

JavaScript如何实现大文件上传的断点续传与秒传?

大文件传输解决方案设计与实施建议 需求分析与现状评估 作为上海IT行业软件公司项目负责人&#xff0c;针对贵司提出的大文件传输功能需求&#xff0c;我进行了全面分析&#xff1a; 核心需求&#xff1a; 单文件100G传输能力文件夹层级结构保持高可靠性断点续传(支持浏览器刷…

作者头像 李华
网站建设 2026/2/14 8:12:07

智能飞船生成新纪元:AI助你轻松打造3D宇宙舰队

智能飞船生成新纪元&#xff1a;AI助你轻松打造3D宇宙舰队 【免费下载链接】SpaceshipGenerator A Blender script to procedurally generate 3D spaceships 项目地址: https://gitcode.com/gh_mirrors/sp/SpaceshipGenerator 还在为复杂的3D建模软件望而却步&#xff1…

作者头像 李华
网站建设 2026/2/19 16:49:26

10个BlenderMCP像素化技巧:让你的3D模型瞬间变身复古游戏资产

还在为3D模型转像素艺术而头疼吗&#xff1f;&#x1f914; 别担心&#xff0c;今天我要分享的BlenderMCP像素化转换技巧&#xff0c;能让你的创作效率翻倍&#xff01;无论你是游戏开发者、像素艺术爱好者&#xff0c;还是想要尝试新风格的3D设计师&#xff0c;这些方法都能帮…

作者头像 李华