javascript模块化

一、CommonJS

CommonJS 是 JavaScript 社区为了解决模块化问题而提出的一种早期规范,它也是 Node.js 环境默认采用的服务器端模块化标准。在 ES6 官方推出原生的模块化方案(ESM)之前,CommonJS 是 Node.js 生态中最主流的模块组织方式。
以下是关于 CommonJS 的核心知识梳理:
 
基础语法:
// 变量名自定义,接收模块导出的内容
const 模块名 = require('模块标识');

💡 核心语法与特性

CommonJS 的核心非常简单,主要包含两个关键字和三个重要特性:
  • 导入与导出:使用 require() 导入模块,使用 module.exports 或 exports 导出模块。
  • 私有作用域:每个 .js 文件都是一个独立的模块,拥有自己的作用域。模块内部定义的变量、函数默认都是私有的,不会污染全局环境,只有通过 module.exports 暴露出去的接口才能被外部访问。
  • 同步加载:执行 require() 时会立即同步加载并执行目标模块。这种方式非常适合 Node.js 服务端(因为文件都在本地硬盘,读取速度极快),但在浏览器端会因为网络请求导致页面阻塞。
  • 值的拷贝:CommonJS 模块导出的是“值的拷贝”(浅拷贝)。也就是说,一旦模块被导出,如果模块内部后续修改了某个变量的值,外部通过 require() 引入的地方是无法感知到这个变化的。
  • 模块缓存:模块在第一次被 require() 后会被缓存起来。后续再次引用同一个模块时,会直接返回缓存的结果,而不会重新加载和执行代码。

实战代码如下:

image

let x = 5;
let addx = function (value) {
    return value + x;
}
module.exports.x = x ;
module.exports.addx = addx;

image

const example = require('./example')
console.log(example)
console.log(example.x)

console.log(example.addx(5))

代码写好之后,在code.js界面中点击右键运行,运行结果如下所示:

image

再看一个实例,如下:

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

// 方式一:整体导出一个对象
module.exports = {
  add,
  subtract
};

// 方式二:通过 exports 扩展导出(注意不能直接给 exports 赋值)
// exports.add = add;
// exports.subtract = subtract;


// main.js (导入模块)
const math = require('./math'); // 同步加载本地的 math 模块

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

下面分析一下CommonJs模块的加载机制:

-commonjs是运行时加载,第一次加载时运行了一次,输出的是值的拷贝;

-es6模块是编译时输出接口;

下面代码对commonjs中的值的拷贝进行说明,如下:

image

let x = 5;
let addx = function (value) {
    return value + x;
}
module.exports.x = x ;
module.exports.addx = addx;

// 说明commonjs值的拷贝的代码
let counter = 3;
function inCounter() {
    counter++;
}
module.exports.counter = counter;
module.exports.incounter = inCounter;

image

const example = require('./example')
console.log(example)
console.log(example.x)

console.log(example.addx(5))

// commonjs值的拷贝的代码
console.log(example.counter);   // 3
example.incounter()
console.log(example.counter)    // 虽然incounter()执行了自加,但仍然是3

继续在code.js中右键运行,输出结果如下:

image

二、没有const 模块名 ,只有require('模块标识')

只写 require('模块标识') 不赋值变量的用法

这种写法叫只执行模块,不接收导出值,非常常见。

1、原理

require() 本身会立刻执行目标模块里的所有代码
 
哪怕你不定义变量接收 module.exports,代码照样跑。

示例 1:只引入、不接收返回值

新建 a.js
// a.js
console.log('我被执行了');

function fn() {
  console.log('函数执行');
}

// 也可以不写 module.exports
 
入口文件 index.js
// 不写 const xx = ,直接写
require('./a');
 
运行输出:
我被执行了
 
👉 效果:加载并执行 a.js 全部代码,但不用它导出的东西

2、常见使用场景

2.1. 引入全局配置、一次性初始化模块

很多框架 / 配置文件只需要加载一次初始化,不用拿返回值:
// 加载并执行数据库连接、全局配置
require('./config/db');
require('./config/global');
 

2.2. 引入扩展原型、全局补丁模块

有些模块会直接修改全局对象、原型,不需要接收变量:
// 给 Promise、数组扩展方法
require('bluebird');
require('./extend/array');
 

2.3. Webpack/Node 入口注册路由、事件

// 一次性注册所有路由文件
require('./routes/user');
require('./routes/goods');
 

3、和赋值写法的区别

// 1. 执行模块 + 接收导出对象
const a = require('./a');

// 2. 只执行模块,不接收导出
require('./a');
 
  • 两种都会完整执行模块代码
  • 区别只在:要不要用它暴露的方法 / 变量

4、一句话总结

require('模块') 单独写不赋值:
 
就是单纯加载并执行这个 JS 文件,不需要使用它向外导出的任何内容

三、ES6模块

ES6 模块(ES Module,简称 ESM)是 JavaScript 官方在 ES6 (ECMAScript 2015) 标准中推出的原生模块化解决方案。它彻底统一了前端与 Node.js 的模块化规范,是现代 JavaScript 工程化开发的基石。
相比于你之前了解的 CommonJS、AMD 和 CMD,ESM 的核心设计理念是“静态化”,即在代码编译阶段就能确定模块之间的依赖关系,从而带来极高的执行效率和强大的工程优化能力。

💡 核心语法与特性

ESM 的核心由 export(导出)和 import(导入)两个命令构成。
  • 两种导出方式
    • 命名导出 (Named Export):一个模块可以多次使用 export 导出多个变量、函数或类。导入时必须使用大括号 {} 包裹对应的名称。
    • 默认导出 (Default Export):一个模块只能有一个 export default。导入时可以自定义任意名称,且不需要大括号。
  • 静态分析import 和 export 必须写在模块的顶层作用域,不能在 if 语句或函数内部使用。这使得打包工具(如 Webpack、Vite)能在构建阶段进行依赖分析和优化(例如 Tree Shaking 摇树优化,剔除未使用的代码)。
  • 值的动态引用 (Live Binding):ESM 导出的不是值的拷贝,而是对原始变量的动态引用。当模块内部的变量发生变化时,所有引入该变量的地方都会同步更新。
  • 严格模式:ESM 自动开启严格模式 ('use strict'),无需手动声明,避免了全局变量污染等常见问题。

基础代码示例

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

// 默认导出
export default function multiply(a, b) {
  return a * b;
}


// main.js (导入模块)
// 混合导入:默认导出直接写变量名,命名导出用 {} 包裹
import multiply, { PI, add } from './math.js'; // 浏览器环境通常需要带 .js 后缀

console.log(multiply(5, 3)); // 输出: 15
console.log(add(5, 3));      // 输出: 8
console.log(PI);             // 输出: 3.14159

 

posted @ 2026-05-17 23:18  chenlight  阅读(5)  评论(0)    收藏  举报