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 进行模块化开发!

相关推荐
沐风清扬4 分钟前
Redis-分布式锁实现秒杀
数据库·redis·分布式·缓存·php
拉不动的猪14 分钟前
刷刷题39(同一组件中的不同的标签页如何实现通信)
前端·javascript·面试
拉不动的猪20 分钟前
刷刷题37(vue3的优化点)
前端·javascript·面试
家里有只小肥猫1 小时前
关于新奇的css
前端·css
南雨北斗1 小时前
jquery ajax 返回TP6错误信息的调试方法
前端·后端
星星不打輰1 小时前
css的显示模式
前端·css
代码CC1 小时前
Vue.js+Element UI 登录界面开发详解【附源码】
前端·vue.js·ui·elementui
无名之逆1 小时前
Hyperlane:Rust 语言打造的 Web 后端框架新标杆
开发语言·前端·网络·网络协议·rust·github·ssl
冰夏之夜影1 小时前
【css酷炫效果】纯CSS实现悬浮弹性按钮
前端·css
shadouqi2 小时前
4.angular 服务
前端·javascript·angular.js