CommonJS API 详解
CommonJS 是一种用于 JavaScript 模块管理的规范,它定义了如何在服务器端和命令行环境中组织和共享代码,与浏览器端的模块系统(如 ES6 模块)不同,CommonJS 主要用于 Node.js 环境,但也可以在浏览器中使用一些工具进行模拟,以下是对 CommonJS API 的详细介绍:
一、模块系统基础
1、模块定义
在 CommonJS 中,一个模块是一个包含特定功能和数据的文件,每个模块都有自己的作用域,其中的变量、函数等不会被墙全局命名空间。
创建一个名为mathModule.js
的文件:
// mathModule.js const add = (a, b) => a + b; const subtract = (a, b) => a b;
2、模块导出(exports)
使用module.exports
可以将函数、对象或原始值从模块中导出,以便其他程序可以通过require
方法使用这些内容。
继续以上面的mathModule.js
为例,如果要导出add
和subtract
函数:
// mathModule.js const add = (a, b) => a + b; const subtract = (a, b) => a b; module.exports = { add, subtract };
3、模块导入(require)
在其他文件中,可以使用require
方法来导入mathModule.js
模块,并使用其中的函数。
在main.js
文件中:
// main.js const math = require('./mathModule'); console.log(math.add(2, 3)); // 输出 5 console.log(math.subtract(5, 2)); // 输出 3
二、核心模块与内置模块
1、核心模块
Node.js 提供了一些核心模块,这些模块是构建在其原生 C++ 库之上的,执行效率较高,它们可以直接通过require
调用,无需指定文件路径。
常见的核心模块包括:
http
:用于创建 HTTP 服务器和客户端请求。
https
:用于处理 HTTPS 协议相关的操作。
fs
:文件系统模块,用于文件读写操作。
path
:提供处理文件路径的工具函数。
使用fs
模块读取文件:
// readFileExample.js const fs = require('fs'); fs.readFile('example.txt', 'utf8', (err, data) => { if (err) { console.error(err); return; } console.log(data); });
2、内置模块
除了核心模块外,Node.js 还有一些内置模块,如assert
(断言模块)、events
(事件模块)等,它们的使用方式与核心模块类似,但在功能上更加专注于特定的领域。
三、常见 API 及用法
1、文件系统(fs)模块
读取文件
fs.readFile(file, [encoding], [callback])
:异步读取文件内容。
fs.readFileSync(file, [encoding])
:同步读取文件内容。
写入文件
fs.writeFile(file, data, [options], callback)
:异步写入文件内容。
fs.writeFileSync(file, data, [options])
:同步写入文件内容。
示例代码:
// fileOperations.js const fs = require('fs'); // 异步读取文件 fs.readFile('input.txt', 'utf8', (err, data) => { if (err) { console.error(err); return; } console.log(data); // 异步写入文件 fs.writeFile('output.txt', data.toUpperCase(), (err) => { if (err) { console.error(err); return; } console.log('File written successfully'); }); });
2、HTTP 模块
创建服务器
http.createServer([requestListener])
:创建一个 HTTP 服务器。
示例代码:
// httpServer.js const http = require('http'); const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello, World! '); }); server.listen(3000, '127.0.0.1', () => { console.log('Server running at http://127.0.0.1:3000/'); });
发送请求
http.get(url, [options], callback)
:发送 HTTP GET 请求。
示例代码:
// httpRequest.js
const http = require('http');
http.get('http://www.example.com', (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log(data);
});
}).on('error', (e) => {
console.error(Got error: ${e.message}
);
});
四、CommonJS 与 ES6 模块的区别
比较项目 | CommonJS | ES6 模块 |
模块定义方式 | 使用module.exports 导出,require 导入 |
使用export 导出,import 导入 |
加载机制 | 运行时加载,整个模块缓存在内存中,再次引用时直接从缓存获取 | 编译时确定依赖关系,支持静态分析优化 |
循环依赖处理 | 可以正常处理循环依赖,但可能会导致一些问题,如多次初始化等 | 不支持循环依赖,会在编译阶段报错 |
默认导出与命名导出 | 只能使用默认导出(module.exports ),没有命名导出的概念 |
可以使用默认导出(export default )和命名导出(export { name1, name2 } ) |
五、相关问答 FAQs
问题 1:CommonJS 模块是否可以在浏览器中使用?
答:虽然 CommonJS 是为服务器端(如 Node.js)设计的模块规范,但在浏览器中也可以通过一些工具(如 Browserify、Webpack 等)将 CommonJS 模块转换为浏览器可识别的格式(如 ES6 模块或通过<script>
标签注入的方式),从而在浏览器中使用,不过,在浏览器原生环境中,并不直接支持 CommonJS 模块语法。
问题 2:CommonJS 模块的缓存机制是怎样的?
答:在 Node.js 中,当使用require
导入一个模块时,该模块会被缓存起来,如果再次导入相同的模块,Node.js 会直接从缓存中获取,而不会再重新执行模块的代码,这意味着模块中的代码在整个应用程序生命周期内只会被执行一次,除非显式地删除缓存或重新启动应用程序,这种缓存机制可以提高性能,但也需要注意可能带来的一些问题,比如模块状态的共享和更新等。