nodejs中相互引用(循环引用)的模块分析

时间:2022-04-01 06:08:12

话不多少,直接上源码吧:

modA.js:

module.exports.test = 'A';
const modB = require('./05_modB');
console.log( 'modA:', modB.test);
module.exports.test = 'AA';

modB.js:

module.exports.test = 'B';
const modA = require('./05_modA');
console.log( 'modB:', modA.test);
module.exports.test = 'BB';

main.js

const modA = require('./modA');

运行结果如下:

nodejs中相互引用(循环引用)的模块分析

刚开始学习和阅读上述代码,是有点觉得晕晕乎乎,如果A与B存在相互依赖、相互引用关系,不就形成了一个闭环或者说死循环?那程序怎么会继续解析呢?很显然,运行结果告诉我们,nodejs引擎有自己的一套处理循环引用的机制。下面我们根据上述运行结果,来推演了两个module模块的执行顺序,以了解nodejs打破闭环的机制。

nodejs中相互引用(循环引用)的模块分析

过程分解:

①执行modA第一行,输出一个test接口

②执行modA第二行,要引入modB此时断点产生了,即开始执行modB里的代码, 程序开始走"breakpoint-out"路线

③执行modB第一行

④执行modB第二行,要因为modA,此步骤为打破闭环的关键,此时将A里断点之前的执行结果输出给modB,如图里的蓝色虚线框标识的部分,此时在modB中打印modA.test,打印'A'

⑤继续执行modB第三行

⑥继续执行modB第四行,对外输出test接口('BB'),此后,modB执行完毕,主程序返回至断点处(modA中在②步骤产生的断点),将modB的执行结果保存在'modB' const变量中。

⑦执行modA的第三行

⑧执行modA的第四行,打印'modB'对象里的test接口,根据中指向结果可知,'modB'返回的test接口为'BB',因此,打印'BB',程序结束。

如果main.js调用的是'modB.js',分析过程完全一致,打印的结果将是'B, AA'。

根据上述分析可知,nodejs中的模块互相引用形成的“闭环”其实是用“断点”这一方式打开的,以断点为出口去执行其他模块,也以断点为入口进行返回,之后继续执行断点之后的代码。

——学无止境,保持好奇。may stars guide your way.