好久沒(méi)更新了,最近在看《深入淺出nodejs》霜旧,就摘一點(diǎn)點(diǎn)下來(lái)吧试吁。
在CommonJS模塊規(guī)范中,每個(gè)模塊文件中存在著require毫别、exports、module這3個(gè)變量典格,但是它們?cè)谀K文件中沒(méi)有定義岛宦,是從哪里來(lái)的呢?甚至在Node的API文檔中耍缴,每個(gè)模塊中還有__filename砾肺、__dirname這兩個(gè)變量的存在,它們又是從何而來(lái)的呢防嗡?
事實(shí)上变汪,在編譯的過(guò)程中,Node對(duì)獲取的JavaScript文件內(nèi)容進(jìn)行了頭尾包裝蚁趁。在頭部添加了(function(exports, require, module, __filename, __dirname){\n,在尾部添加了\n}); 裙盾。一個(gè)正常的JavaScript文件會(huì)被包裝成如下的樣子:
(function (exports, require, module, _ _ filename, _ _ dirname) {
? ? var math = require('math');
? ? exports.area = function(radius){
????????return Math.PI * radius * radius;
? ? };
});
這樣每個(gè)模塊文件之間都進(jìn)行了作用域隔離。包裝之后的代碼會(huì)通過(guò)vm原生模塊的runInThisContext()方法執(zhí)行(類似eval,只是具有明確上下文闷煤,不污染全局)童芹,返回一個(gè)具體的function對(duì)象。最后鲤拿,將當(dāng)前模塊對(duì)象的exports屬性假褪,require()方法,module(模塊對(duì)象自身)近顷,以及在文件定位中得到的完整路徑和文件目錄作為參數(shù)傳遞給這個(gè)function()執(zhí)行生音。
這就是這些變量并沒(méi)有定義在每個(gè)模塊文件中確存在的原因。在執(zhí)行之后窒升,模塊的exports屬性被返回給了調(diào)用方缀遍。exports屬性上的任何方法和屬性都可以被外部調(diào)用到,但是模塊中的其余變量或?qū)傩詣t不可直接被調(diào)用饱须。
這就是Node對(duì)CommonJS模塊規(guī)范的實(shí)現(xiàn)域醇。
以上摘自《深入淺出nodejs》。