JS循环引用问题

import 和 require

import

是ES6出的模块化方案,其目的是尽量静态化,所以ES6的模块化是编译时解析

require

是运行时解析,是一个值得拷贝,是属于浅拷贝
当使用require命令加载同一个模块时,不会再执行该模块,而是取到缓存之中的值。也就是说,commonjs模块无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非手动清除系统缓存。

循环加载时,属于加载时执行。即脚本代码在require的时候,就会全部执行。一旦出现某个模块被”循环加载”,就只输出已经执行的部分,还未执行的部分不会输出。

问题如此:

写nodejs时碰到令人头疼的require循环引用问题
GitHub issue链接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//  a.js
const { bbb } = require('./b')
function aaa(num) {
if (num % 2 == 0) {
console.log(num)
bbb(num);

}
}
module.exports = { aaa };

// b.js
const { aaa } = require('./a');
function bbb(num) {
if (num%2==0) {
num = num / 2;
console.log(num);
aaa(num);
}
return 'bbb'
}
module.exports = { bbb };

// index.js
var {aaa} = require('./a');
aaa(100)

运行后报错如下
报错详情
这是因为node的require语法处理的结果,如果是对象之间循环引用的话会变为空对象。

解决办法:

将a.js的const { bbb } = require('./b')写在module.exports下面

1
2
3
4
5
6
7
8
9
function aaa(num) {
if (num % 2 == 0) {
console.log(num)
bbb(num);

}
}
module.exports = { aaa };
const { bbb } = require('./b')

这样就可以运行,因为在加载b文件前先导出了aaa函数,能够运行。