循環引用是模塊系統裏一個避免不了的話題,能夠加以討論javascript
When there are circular require() calls, a module might not have finished executing when it is returned.html
當在代碼中出現循環 require 引用時,模塊可能不會在返回結果前結束執行java
Consider this situation:node
考慮這個情景:api
a.jsapp
console.log('a starting'); exports.done = false; const b = require('./b.js'); console.log('in a, b.done = %j', b.done); exports.done = true; console.log('a done');
b.jside
console.log('b starting'); exports.done = false; const a = require('./a.js'); console.log('in b, a.done = %j', a.done); exports.done = true; console.log('b done');
main.jsoop
console.log('main starting'); const a = require('./a.js'); const b = require('./b.js'); console.log('in main, a.done=%j, b.done=%j', a.done, b.done);
When main.js loads a.js, then a.js in turn loads b.js. At that point, b.js tries to load a.js. In order to prevent an infinite loop, an unfinished copy of the a.js exports object is returned to the b.js module. b.js then finishes loading, and its exports object is provided to the a.js module.ui
當 main.js 加載 a.js 時,a.js 依次加載 b.js。這時,b.js 試圖加載 a.js。爲了防止無限循環,將 a.js exports 對象的未完成副本返回給 b.js 模塊(就是 const b = require('./b.js');
的上面那行 exports.down = false;
)。 而後 b.js 完成加載,並將其導出對象提供給 a.js 模塊。this
By the time main.js has loaded both modules, they're both finished. The output of this program would thus be:
此時 main.js 完成對這兩個模塊的加載,最後程序的輸出以下:
$ node main.js main starting a starting b starting in b, a.done = false b done in a, b.done = true a done in main, a.done=true, b.done=true
Careful planning is required to allow cyclic module dependencies to work correctly within an application.
要當心設計模塊,來使得循環模塊依賴項能在程序里正常工做。
一般循環引用後最後碰上 undefined,由於它並不會在代碼中段 exports 值,import 的時候就只會是 undefined。
總的來講,循環依賴的陷阱並不大容易出現,但一旦出現了,對於新手來講還真很差定位。它的存在給咱們提了個醒,要時刻注意你項目的依賴關係不要過於複雜,哪天你發現一個你明明已經 exports 了的方法報 undefined is not a function,那就該警醒。
寫到這裏才發現原來 Node 官網早已經有了中英文對照版本,不過我仍是爲文一記吧。