为什么模块级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 .js

Module._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 function

var 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 });

然后终于,模块的编译包装的函数对象调用像这样,以填充值exportsrequiremodule__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

回到顶部