为什么模块级return语句在Node.js中起作用?
当我回答另一个问题时我遇到了一个带有顶层return
语句的Node.js模块。例如:
console.log("Trying to reach");return;
console.log("dead code");
这可以正常工作并且没有错误并可以打印:
Trying to reach
在标准输出中,但不是“ dead code
”- return
实际停止执行。
但是根据ECMAScript
5.1中的return
语句规范,
如果ECMAScript程序 包含不在内的return语句,则在语法上
FunctionBody
_被视为 _不正确 。
在上面显示的程序中return
没有任何功能。
回答:
Node.js将模块包装在一个函数中,如下所示:
(function (exports, require, module, __filename, __dirname) { // our actual module code
});
所以上面显示的代码实际上是由Node.js执行的,就像这样
(function (exports, require, module, __filename, __dirname) { console.log("Trying to reach");
return;
console.log("dead code");
});
这就是程序仅打印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.
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 types
require.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});'
];
然后包装的功能是编译和执行在这里用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
语句可以正常运行的原因。
以上是 为什么模块级return语句在Node.js中起作用? 的全部内容, 来源链接: utcz.com/qa/399767.html