TL; DR
Node.js将模块包装在一个函数中,如下所示:
(function (exports, require, module, __filename, __dirname) { // our actual module pre});所以上面显示的代码实际上是由Node.js执行的,就像这样
(function (exports, require, module, __filename, __dirname) { console.log("Trying to reach"); return; console.log("dead pre");});这就是程序仅打印
Trying to reach并跳过
console.log以下
return语句的原因。
内部构造
这是我们需要了解Node.js如何处理模块的地方。当您使用Node.js运行.js文件时,它将文件视为一个模块,并使用v8
Javascript引擎对其进行编译。
它与所有启动
runMain功能,
// bootstrap main module.Module.runMain = function() { // Load the main module--the command line argument. Module._load(process.argv[1], null, true); // Handle any nextTicks added in the first tick of the program process._tickCallback();};在该
Module._load函数中,将创建一个新的Module对象并进行加载。
var module = new Module(filename, parent);......try { module.load(filename); hadException = false;该
Module功能
load做到这一点,
// Given a file name, pass it to the proper extension handler.Module.prototype.load = function(filename) { debug('load ' + JSON.stringify(filename) + ' for module ' + JSON.stringify(this.id)); assert(!this.loaded); this.filename = filename; this.paths = Module._nodeModulePaths(path.dirname(filename)); var extension = path.extname(filename) || '.js'; if (!Module._extensions[extension]) extension = '.js'; Module._extensions[extension](this, filename); this.loaded = true;};由于文件的扩展名是
js,因此我们可以看到
Module._extensions它的作用
.js。可以在这里看到
// Native extension for .jsModule._extensions['.js'] = function(module, filename) { var content = fs.readFileSync(filename, 'utf8'); module._compile(stripBOM(content), filename);};该
module物体
_compile在该函数调用,这就是魔法发生,
// Run the file contents in the correct scope or sandbox. Expose// the correct helper variables (require, module, exports) to// the file.// Returns exception, if any.
这是require
我们的节点模块使用的函数首先创建的地方。
function require(path) { return self.require(path);}require.resolve = function(request) { return Module._resolveFilename(request, self);};Object.defineProperty(require, 'paths', { get: function() { throw new Error('require.paths is removed. Use ' + 'node_modules folders, or the NODE_PATH ' + 'environment variable instead.');}});require.main = process.mainModule;// Enable support to add extra extension typesrequire.extensions = Module._extensions;require.registerExtension = function() { throw new Error('require.registerExtension() removed. Use ' + 'require.extensions instead.');};require.cache = Module._cache;然后是包装代码的一些事情,
// create wrapper functionvar wrapper = Module.wrap(content);
我们着手寻找能做什么
Module.wrap,那不过是什么
Module.wrap = NativeModule.wrap;
在
src/node.js文件中定义的,这就是我们在其中找到的位置,
NativeModule.wrap = function(script) { return NativeModule.wrapper[0] + script + NativeModule.wrapper[1];};NativeModule.wrapper = [ '(function (exports, require, module, __filename, __dirname) { ', 'n});'];这是我们的程序是如何有机会获得神奇的变量,exports
,require
,module
,__filename
和__dirname
然后包装的功能是编译和执行在这里用
runInThisContext,
var compiledWrapper = runInThisContext(wrapper, { filename: filename });然后终于,模块的编译包装的函数对象调用像这样,以填充值
exports,
require,
module,
__filename和
__dirname
var args = [self.exports, require, self, filename, dirname];return compiledWrapper.apply(self.exports, args);
这就是Node.js处理和执行我们的模块的方式,这就是为什么该
return语句可以正常运行的原因。



