// test.js 位于 E:\projects\node\node-demo目录下,在当前目录执行 node test.js console.log("__dirname", __dirname); console.log("__filename", __filename); console.log("exports", exports); console.log("module", module); console.log("require", require);打印结果如下:
// 堆代码 duidaima.com // node\lib\internal\modules\cjs\loader.js Module.prototype._compile = function(content, filename) { ...... const compiledWrapper = wrapSafe(filename, content, this); ...... }; let wrap = function(script) { // eslint-disable-line func-style return Module.wrapper[0] + script + Module.wrapper[1]; }; const wrapper = [ '(function (exports, require, module, __filename, __dirname) { ', '\n});', ]; function wrapSafe(filename, content, cjsModuleInstance, codeCache) { ...... if (patched) { const wrapped = Module.wrap(content); const script = makeContextifyScript( wrapped, // code filename, // filename 0, // lineOffset 0, // columnOffset undefined, // cachedData false, // produceCachedData undefined, // parsingContext hostDefinedOptionId, // hostDefinedOptionId importModuleDynamically, // importModuleDynamically ); ...... return runScriptInThisContext(script, true, false); } const params = [ 'exports', 'require', 'module', '__filename', '__dirname' ]; try { const result = internalCompileFunction( content, // code, filename, // filename 0, // lineOffset 0, // columnOffset, codeCache, // cachedData false, // produceCachedData undefined, // parsingContext undefined, // contextExtensions params, // params hostDefinedOptionId, // hostDefinedOptionId importModuleDynamically, // importModuleDynamically ); ...... return result.function; } catch (err) { ...... } }重点就是 wrapSafe()、wrap()、wrapper
编译时,_compile 调用 wrapSafe ,wrapSafe 这个函数将 content 包装在一个脚本(wrapper)中,并在新的上下文中运行它,这个 content 就是我们写的 js 文件中的内容。
当执行 node app.js,开始编译这个文件,wrapSafe 函数会将这个 js 文件中的所有内容先拼接成 '(function (exports, require, module, __filename, __dirname) { console.log(__dirname); \n});' 这样一个字符串(即调用 Module.wrap(content)),再将它转化为一个可执行脚本(即调用 makeContextifyScript),然后在当前上下文中执行(即调用 runScriptInThisContext)。