話不多少,直接上源碼吧:
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');
運行結果如下:
剛開始學習和閱讀上述代碼,是有點覺得暈暈乎乎,如果A與B存在相互依賴、相互引用關系,不就形成了一個閉環或者說死循環?那程序怎么會繼續解析呢?很顯然,運行結果告訴我們,nodejs引擎有自己的一套處理循環引用的機制。下面我們根據上述運行結果,來推演了兩個module模塊的執行順序,以了解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.