NodeJS中require()调用后导出成员的值变更会产生什么效果?
CommonJS模块运行核心规则
- 当调用
require()加载某模块时,Node会同步执行该模块内的所有顶层代码,执行完成后才会将module.exports指向的值返回给引入方 module.exports本身遵循常规JavaScript赋值逻辑:- 赋值基础类型(undefined、null、数字、字符串等)时,直接赋值对应值
- 赋值引用类型(对象、数组、函数)时,赋值的是该值的内存引用
第一组测试报错原因
exporter.js执行顺序如下:
- 声明变量
c,默认值为undefined - 执行
module.exports = c:此时将undefined直接赋值给module.exports - 执行
c = {c_key1: 100}:仅将变量c的指向改为新的对象,不会修改已经赋值给module.exports的undefined - 后续修改
c.c_key1的操作都是针对新对象,和module.exports没有任何关联
最终require('./exporter.js')拿到的结果就是undefined,访问.c_key1自然触发类型错误。
第二组测试输出0的原因
修改后的exporter.js执行顺序如下:
- 声明变量
c,默认值为undefined - 执行
c = {c_key1: 100}:将c指向一个新对象,对应内存地址记为地址A - 执行
module.exports = c:将module.exports也指向地址A的同一个对象 - 执行
c.c_key1 = 0:修改地址A上的对象属性,module.exports指向的就是这个对象,属性会同步变更
最终require()拿到的就是地址A上的对象,c_key1已经被修改为0,所以输出0。
常见误解澄清
之前认为「只有module.exports赋值之前的语句才会生效」的认知是错误的:
模块内所有代码都会执行,只需区分操作的本质:
- 如果在
module.exports赋值之后,修改的是module.exports指向的引用类型的内部属性,变更会同步到引入方拿到的值 - 如果在
module.exports赋值之后,只是修改了之前用来赋值的普通变量的指向,不会影响module.exports的最终值
内容的提问来源于stack exchange,提问作者Woo
相关产品推荐
相关产品推荐

