CommonJS是一种用于定义JavaScript模块的规范,它的目的是为了让JavaScript代码在不同的环境中运行,包括浏览器和服务器端。CommonJS规范主要包括模块定义、模块引用、模块标识符、模块循环依赖、核心模块等几个方面。
1. 模块定义
在CommonJS规范中,每个文件都被视为一个独立的模块,模块可以通过module.exports或exports对象将自己的接口暴露给其他模块使用。其中,module.exports是一个特殊的对象,表示模块的输出,而exports对象是module.exports的一个引用,可以用来方便地向外部暴露接口。
例如,下面的代码定义了一个简单的模块:
// 定义模块 add.js
function add(a, b) {
return a + b;
}
module.exports = add;
在另一个文件中,可以使用require函数引入这个模块:
// 引入 add 模块
const add = require('./add.js');
// 使用 add 模块中的函数
console.log(add(1, 2)); // 输出 3
2. 模块引用
在CommonJS规范中,使用require函数引入其他模块。require函数的参数是模块的路径,可以是相对路径或绝对路径。如果是相对路径,则相对于当前模块所在的目录。
例如,上面的代码中,使用require函数引入了add.js模块,其参数是相对路径'./add.js'。
3. 模块标识符
模块的标识符是一个字符串,用于标识模块。在Node.js中,模块的标识符通常是模块的文件路径。例如,在上面的代码中,'./add.js'就是add模块的标识符。
4. 模块循环依赖
CommonJS规范允许模块之间进行循环依赖,即模块A可以引用模块B,同时模块B也可以引用模块A。在处理循环依赖时,Node.js使用了一种延迟加载
的策略,即在引入模块时,先创建一个空对象,然后将这个空对象作为模块的输出返回。当模块加载完成后,再将真正的输出赋值给这个空对象。
例如,下面的代码展示了一个包含循环依赖的模块:
// 定义模块 A
const B = require('./B.js');
console.log('A loaded');
module.exports = {
name: 'module A',
b: B
};
// 定义模块 B
const A = require('./A.js');
console.log('B loaded');
module.exports = {
name: 'module B',
a: A
}
5. 核心模块
CommonJS规范还定义了一些核心模块,可以通过require函数直接引用。这些核心模块包括:
- assert:断言模块,用于测试代码是否符合预期。
- buffer:二进制数据模块,用于处理二进制数据。
- child_process:子进程模块,用于创建和管理子进程。
- cluster:集群模块,用于创建和管理多个进程。
- console:控制台模块,用于输出日志和调试信息。
- events:事件模块,用于实现事件驱动编程。
- fs:文件系统模块,用于读写文件和目录操作。
- http:HTTP模块,用于创建和管理HTTP服务器和客户端。
- net:网络模块,用于创建和管理TCP服务器和客户端。
- os:操作系统模块,用于获取操作系统信息。
- path:路径模块,用于处理文件路径。
- process:进程模块,用于获取和控制当前进程信息。
- querystring:查询字符串模块,用于解析和序列化URL查询字符串。
- stream:流模块,用于处理数据流。
- timers:定时器模块,用于延时和定时执行函数。
- url:URL模块,用于解析和格式化URL。
- util:实用工具模块,提供一些常用的工具函数。
- vm:虚拟机模块,用于执行JavaScript代码。
这些核心模块可以在Node.js中直接使用,例如:
const fs = require('fs');
const http = require('http');
const path = require('path');
// ...
总结
CommonJS规范定义了一种简单的模块系统,允许JavaScript代码在不同的环境中运行,包括浏览器和服务器端。模块系统通过模块定义、模块引用、模块标识符、模块循环依赖、核心模块等方面进行规范。通过使用这些规范,开发者可以更加方便地编写和管理复杂的JavaScript应用程序。