js 循环获取不定参转成变量_requrie 循环引用

前言

最近拜读了阮老师的一篇文章

nodejs require实现解析​www.ruanyifeng.com
9d6ae5e41bec3011bfd9e061f35becd1.png

看完之后便产生了一个疑问,a文件与b文件之间相互循环引用,那么,会产生什么情况

// file a.js
const b = require('./a.js')

// file b.js
const a = requrie('./b.js')

代码实践

// file a.js
const b = require('./b.js')

console.log('require b : ')
console.log(b)

// 重定向 exports 引用对象
// module.exports = {}
module.exports.aTest = '777'

// ----------------------------------

// file b.js
const a = require('./a.js')

console.log('requrie a :')
console.log(a)

module.exports.bTest = '666'

setTimeout(() => {
    console.log('time out requrie a :')
    console.log(a)
} , 1000)

上述代码的结果为:

requrie a :Object { }
require b : Object { bTest: "666" }
time out requrie a : Object { aTest: "777" }

当打开注释,重定向module.exports之后,代码结果为:

requrie a : Object { }
require b : Object { bTest: "666" }
time out requrie a :Object { }

结果分析

首先我们分析第一个结果,通过对于require的源码阅读可知,缓存的是整个module对象,其在初始化的时候,会将exports属性初始化为一个空对象,我们给这个对象暂且命名为 ORIGINAL

我们的入口是a.js,解析器开始解析代码,遇到了require('./b.js')

但此时,模块b.js并没有被创建,也没有任何缓存,故而,进入b.js的解析过程

b.js文件中第一行便是require('a.js'),虽然此时a.js模块此时还处于解析阶段,但是其对应module已经被缓存,故而我们可以拿到其exports值ORIGINAL(此时依旧是空对象)

当b.js模块解析完成之后,便返回到了a.js模块的解析,console.log(b)正常输出了b.js导出的对象

然后,a.js中执行了导出操作,在此代码中,其内在操作 = 修改了ORIGINAL对象的属性,至此,a.js解析执行完成

1S之后,计时器回调函数执行,再次打印a变量

由结果可以看出,此时,我们正确获取到了a.js的导出信息,由此可见,在上述代码中,其他模块require的值,模块本身的module.exports都引用的是同一个对象ORIGINAL

接着我们来分析第二个结果,也就是当我们打开了注释,将a.js的module.exports重新赋值

通过对比我们发现,在1S之后,回调函数打印出来的依旧是一个空对象,其原因在于

module会在解析编译之前缓存,然后在编译的时候作为模块的全局变量“注入”到文件中,故而,在代码中的module和缓存起来的module引用的是同一个对象

我们将module.exports重新赋值重新赋值的对象称之为ANOTHER

当执行完重赋值之后,缓存中的module.exports也从ORIGINAL更新为ANOTHER,但是需注意,就如结果一中分析的那样,在b.js中,我们require的结果是ORIGINAL,故而对于ANOTHER的修改当然在b.js中获取不到,ORIGINAL依旧为一个空对象

建议

  • 不要module.exports进行赋值操作
  • 尽量避免出现循环引用的行为,如出现,则需谨慎处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值