请解释 CommonJS 模块规范的核心内容,并说明 Node.js 在运行时是如何落实这一模块机制的?
考察说明
考察对 CommonJS 模块规范及其在 Node.js 中实现原理的理解。
回答思路
- 【回答框架 1】CommonJS 是一种模块规范,核心包括模块引用、模块定义和模块标识。每个文件是一个模块,内部变量和函数默认不暴露,通过 module.exports 或 exports 导出,require 导入。
- 【回答框架 2】Node.js 实现时,每个模块被包装在一个函数中,例如 (function(exports, require, module, __filename, __dirname) { ... }),以此隔离作用域,并将 require、module 等作为参数注入。
- 【回答框架 3】require 加载模块的流程是:解析路径、缓存检查、加载并执行模块代码、返回模块的 exports 对象。模块首次加载后会缓存,之后 require 返回缓存对象。
- 【回答框架 4】module.exports 和 exports 的关系是:exports 初始指向 module.exports,直接对 exports 赋值会切断引用,应使用 module.exports 或对 exports 添加属性。
- 【回答框架 5】加载机制与文件扩展名解析顺序相关,例如 .js、.json、.node,且支持目录模块通过 package.json 的 main 字段指定入口。
- 【关键点 1】CommonJS 模块规范包含模块引用、定义和标识三部分。
- 【关键点 2】Node.js 通过函数包装实现模块作用域隔离。
- 【关键点 3】require 加载模块经过路径解析、缓存检查、执行和返回 exports 的过程。
- 【关键点 4】exports 是 module.exports 的引用,直接赋值 exports 不会改变模块导出。
- 【关键点 5】模块缓存导致多次 require 只执行一次模块代码。
- 【易错点 1】容易混淆 exports 和 module.exports 的赋值行为。
- 【易错点 2】忽略 require 缓存机制而误以为模块会重复执行。
- 【易错点 3】未考虑循环依赖时可能得到不完整的 exports 对象。