Node.js--CommonJS 模块化规范详解:使用方法、缓存机制与模块解析

目录

[Node.js CommonJS 模块化规范详解](#Node.js CommonJS 模块化规范详解)

[1. CommonJS 模块化规范简介](#1. CommonJS 模块化规范简介)

[CommonJS 主要特点](#CommonJS 主要特点)

[2. CommonJS 模块的基本使用](#2. CommonJS 模块的基本使用)

示例1:导出和导入模块

运行程序

[3. module.exports vs exports 的使用](#3. module.exports vs exports 的使用)

[示例2:使用 exports 导出多个方法](#示例2:使用 exports 导出多个方法)

[示例3:使用 module.exports 导出单个函数](#示例3:使用 module.exports 导出单个函数)

[4. CommonJS 的模块缓存机制](#4. CommonJS 的模块缓存机制)

示例4:模块缓存机制

[5. CommonJS 的 require 解析规则](#5. CommonJS 的 require 解析规则)

[6. 结论](#6. 结论)

在 Node.js 中,CommonJS(CJS)是最常见的模块化规范,它允许开发者将代码拆分为独立的模块,便于复用和管理。本文将详细介绍 CommonJS 的核心概念、使用方法,并提供完整代码示例,帮助你深入理解并应用 CommonJS 进行模块化开发。


1. CommonJS 模块化规范简介

CommonJS 规范的核心思想是一个文件就是一个模块 ,每个模块都有自己的作用域,默认情况下,模块内部定义的变量、函数、对象等不会污染全局作用域

CommonJS 主要特点

  1. require 导入模块
  2. module.exports / exports 导出模块
  3. 同步加载(适用于服务器端)
  4. 模块缓存(require 同一个模块时不会重复加载)

2. CommonJS 模块的基本使用

示例1:导出和导入模块

创建 math.js,定义数学计算功能,并使用 module.exports 导出。

文件名:math.js(JavaScript)

javascript 复制代码
// math.js
const mathOperations = {
    add: (a, b) => a + b,
    subtract: (a, b) => a - b,
    multiply: (a, b) => a * b,
    divide: (a, b) => (b !== 0 ? a / b : "Error: Division by zero")
};

// 导出模块
module.exports = mathOperations;

文件名:app.js(JavaScript)

javascript 复制代码
// app.js
const math = require("./math"); // 使用 require 导入模块

console.log("加法 5 + 3 =", math.add(5, 3)); 
console.log("减法 10 - 4 =", math.subtract(10, 4)); 
console.log("乘法 6 * 7 =", math.multiply(6, 7)); 
console.log("除法 20 / 5 =", math.divide(20, 5)); 
console.log("除法 10 / 0 =", math.divide(10, 0)); // 测试除数为0的情况

运行程序

bash 复制代码
node app.js

输出结果

bash 复制代码
加法 5 + 3 = 8
减法 10 - 4 = 6
乘法 6 * 7 = 42
除法 20 / 5 = 4
除法 10 / 0 = Error: Division by zero

3. module.exports vs exports 的使用

在 CommonJS 规范中,module.exports 是实际的导出对象,而 exports 只是它的引用。

示例2:使用 exports 导出多个方法

文件名:stringUtils.js(JavaScript)

javascript 复制代码
// stringUtils.js
exports.toUpperCase = function (str) {
    return str.toUpperCase();
};

exports.toLowerCase = function (str) {
    return str.toLowerCase();
};

文件名:app.js(JavaScript)

javascript 复制代码
// app.js
const stringUtils = require("./stringUtils");

console.log(stringUtils.toUpperCase("hello")); // 输出: HELLO
console.log(stringUtils.toLowerCase("WORLD")); // 输出: world

运行程序

bash 复制代码
node app.js

输出结果

bash 复制代码
HELLO
world

示例3:使用 module.exports 导出单个函数

文件名:greet.js(JavaScript)

javascript 复制代码
// greet.js
module.exports = function(name) {
    return `Hello, ${name}!`;
};

文件名:app.js(JavaScript)

javascript 复制代码
// app.js
const greet = require("./greet");
console.log(greet("鼠鼠"));

运行程序

bash 复制代码
node app.js

输出

javascript 复制代码
Hello, 鼠鼠!

4. CommonJS 的模块缓存机制

在 CommonJS 规范下,require 只会第一次加载 模块时执行其中的代码,之后会缓存模块内容,再次 require 时不会重新执行模块,而是直接返回缓存的结果。

示例4:模块缓存机制

文件名:counter.js(JavaScript)

javascript 复制代码
// counter.js
let count = 0;

exports.increment = function () {
    count++;
    return count;
};

文件名:app.js(JavaScript)

javascript 复制代码
// app.js
const counter1 = require("./counter");
const counter2 = require("./counter");

console.log(counter1.increment()); // 输出: 1
console.log(counter2.increment()); // 输出: 2 (同一个缓存实例)
console.log(counter1.increment()); // 输出: 3

运行程序

bash 复制代码
node app.js

输出结果

bash 复制代码
1
2
3

解释

  • require("./counter") 只在第一次执行 counter.js 的代码,count 被缓存。
  • 后续 require("./counter") 直接返回缓存的 count 变量,而不是重新执行 counter.js 文件。

5. CommonJS 的 require 解析规则

在使用 require() 导入模块时,Node.js 会按以下顺序解析模块路径:

  1. 内置模块 (如 fspath 等)
  2. 文件模块
    • require('./math')(加载 math.js
    • require('../utils')(加载上一级目录的 utils.js
  3. 第三方模块 (默认在 node_modules 查找)
    • require('express')(加载 node_modules/express 目录下的 index.js
  4. 目录模块
    • 如果 require('./myModule') 指向的是一个文件夹,Node.js 会查找该文件夹中的 package.json,尝试加载 main 字段指向的文件。
    • 如果 package.json 不存在或 main 字段未定义,则尝试加载 index.js

6. 结论

  • CommonJS 规范 使用 module.exports 导出模块,require 导入模块。
  • 模块作用域:每个文件是一个独立的模块,变量不会污染全局。
  • 模块缓存require 只会执行模块一次,之后直接返回缓存的对象。
  • module.exports vs exportsexports 只是 module.exports 的引用,不能直接赋值 exports = {...},否则会失效。
  • 模块解析规则 :Node.js 先查找内置模块,再查找文件模块,最后查找 node_modules 目录。

希望这篇文章能帮助你理解 Node.js CommonJS 模块化规范,掌握如何使用 module.exportsrequire 进行模块化开发!

相关推荐
Mintopia2 分钟前
3D Quickhull 算法:用可见性与冲突图搭建空间凸壳
前端·javascript·计算机图形学
Mintopia3 分钟前
Three.js 三维数据交互与高并发优化:从点云到地图的底层修炼
前端·javascript·three.js
新手小黑吖6 分钟前
vscode开发微信小程序
vscode·微信小程序
陌小路8 分钟前
5天 Vibe Coding 出一个在线音乐分享空间应用是什么体验
前端·aigc·vibecoding
成长ing1213816 分钟前
cocos creator 3.x shader 流光
前端·cocos creator
Alo36525 分钟前
antd 组件部分API使用方法
前端
BillKu27 分钟前
Vue3数组去重方法总结
前端·javascript·vue.js
GDAL30 分钟前
Object.freeze() 深度解析:不可变性的实现与实战指南
javascript·freeze
江城开朗的豌豆1 小时前
Vue+JSX真香现场:告别模板语法,解锁新姿势!
前端·javascript·vue.js