引入模块
在 Node.js 中,CommonJS 是一种用于定义模块的标准。引入一个模块通常使用 require
函数来完成。例如,如果你想引入 fs
模块,可以这样写:
const fs = require('fs');
这个过程实际上会创建一个模块上下文,然后执行该模块的代码,最后返回一个对象。这个对象包含了该模块对外暴露的内容。
导出模块
为了导出模块中的变量、函数或对象,你可以使用 module.exports
或 exports
对象。它们都可以用来导出模块内容,但需要注意的是,exports
实际上是 module.exports
的一个引用。
使用 module.exports 导出
module.exports
可以直接赋值为任何 JavaScript 类型的对象,包括函数、数组、字符串等。例如:
// myModule.js module.exports = { name: 'My Module', version: '1.0.0' };
使用 exports 导出
exports
是 module.exports
的一个引用,因此可以直接通过它来添加属性和方法。例如:
// myModule.js exports.name = 'My Module'; exports.version = '1.0.0'; exports.logInfo = function() { console.log(`Module Name: ${this.name}, Version: ${this.version}`); };
使用 exports 和 module.exports 的区别
虽然 exports
可以方便地添加属性和方法,但如果需要将整个模块导出为一个特定的对象,则必须直接使用 module.exports
。例如:
-- -------------------- ---- ------- -- ----------- ------------ - --- -------- -- -- ------- ---- --------------- - -------- -- ----------------- -------------- -------------- - - -------- ---------- - ------------------- ----- ------------- -------- ------------------ - --
模块作用域
每个模块都有自己的作用域,这意味着模块内部定义的变量和函数不会污染全局作用域。例如,在模块中定义的变量和函数不会在其他模块或全局环境中被访问到。
模块内部的变量和函数
假设你在模块中定义了一个变量和一个函数:
// myModule.js let secret = 'This is a secret!'; function getSecret() { return secret; } module.exports.getSecret = getSecret;
在这个例子中,外部无法直接访问 secret
变量,只能通过 getSecret
函数获取其值。
模块缓存机制
Node.js 会对已经加载过的模块进行缓存,这意味着如果多次使用 require
加载同一个模块,Node.js 会返回缓存中的实例,而不是重新加载模块代码。这有助于提高性能,但需要注意,这也意味着修改了模块文件后,需要重启 Node.js 应用才能使更改生效。
如何强制重新加载模块
如果你确实需要重新加载模块,可以使用 delete require.cache[require.resolve('./myModule')]
来删除缓存,从而迫使 Node.js 重新加载模块。
delete require.cache[require.resolve('./myModule')]; const myModule = require('./myModule');
这样就可以确保每次加载时都得到最新的模块内容。
模块路径解析
当使用 require
加载模块时,Node.js 会按照一定的规则来解析模块路径。默认情况下,Node.js 会首先尝试在当前目录下寻找指定的模块。如果找不到,则会继续搜索父目录,直到找到模块或到达文件系统的根目录为止。
绝对路径和相对路径
- 绝对路径:从文件系统的根目录开始的路径。
- 相对路径:相对于当前模块文件的位置。
使用 node_modules 目录
Node.js 还会在 node_modules
目录中查找模块。当你安装第三方库时,这些库通常会被安装到项目根目录下的 node_modules
文件夹中。通过这种方式,可以很容易地在项目中使用这些库。
示例
假设你的项目结构如下:
/project-root /node_modules /lib myModule.js app.js
在 app.js
中引入 myModule.js
可以这样做:
const myModule = require('./lib/myModule');
这样,Node.js 会先在当前目录(app.js
所在目录)的 lib
子目录中查找 myModule.js
。
总结
本章介绍了 Node.js 中如何使用 CommonJS 规范来管理模块。通过了解如何引入、导出模块,以及模块的作用域、缓存机制和路径解析,你可以更好地组织和维护你的代码。接下来的章节将进一步深入讨论 Node.js 的其他核心概念和高级功能。