当我回答another question时,我遇到了一个 node .带有顶级return语句的js模块.例如:

console.log("Trying to reach");
return;
console.log("dead code");

这可以打印without any errors张照片:

Trying to reach

在标准输出中,但不是"dead code"——return实际上停止了执行.

但根据specification of return statements in ECMAScript 5.1人的说法,

Semantics

ECMAScript程序被认为是syntactically incorrect if it contains a return statement that is not within a 100.

在上面显示的程序中,return不在任何功能范围内.

Then why doesn't this throw?

推荐答案

TL;DR

模块由 node 包装.函数中的js,如下所示:

(function (exports, require, module, __filename, __dirname) {
    // our actual module code
});

所以上面显示的代码实际上是由 node 执行的.像这样

(function (exports, require, module, __filename, __dirname) {
    console.log("Trying to reach");
    return;
    console.log("dead code");
});

这就是为什么程序只打印Trying to reach,并跳过return语句后面的console.log.

Internals

这就是我们需要了解 node 如何工作的地方.js处理模块.当你 run 的时候.带有 node 的js文件.js,它将其视为一个模块,并使用v8 JavaScript引擎进行编译.

都是从runMain function开始的,

// 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函数中,使用new Module object is createdit is loaded.

var module = new Module(filename, parent);
...
...
try {
  module.load(filename);
  hadException = false;

Module function's load does this人,

// 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.可以看到here

// 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.

This is where the 100 function, used by our node modules's is created first.

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的作用,which is nothing but

Module.wrap = NativeModule.wrap;

这就是我们发现这个的地方,

NativeModule.wrap = function(script) {
  return NativeModule.wrapper[0] + script + NativeModule.wrapper[1];
};

NativeModule.wrapper = [
  '(function (exports, require, module, __filename, __dirname) { ',
  '\n});'
];

This is how our programs have access to the magic variables, 100, 101, 102, 103 and 104

然后编译并执行包装函数hererunInThisContext

var compiledWrapper = runInThisContext(wrapper, { filename: filename });

最后,调用模块编译后的包装函数对象,如this,并填充exportsrequiremodule__filename__dirname的值

var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);

这就是 node 处理和执行模块的方式.这就是为什么return语句能够正常工作.

Node.js相关问答推荐

Windows上使用ES6+的OpenAPI规范的Express服务器不接受嵌套路由'

使用NodeJS在S3上传文件时的格式问题

MongoDB如果文档S的字段小于另一个字段,则将该字段加一

Gmail API获取附件PDF未正确呈现.我遗漏了什么?

聚合操作不返回任何具有mongoose模式的内容

为什么 mongoose 没有常规数组方法

GitLab 依赖扫描需要源代码中的 package-lock.json 才能执行

具有项目外部子路径导入的 Firebase 函数

结合后端(Express)和前端(Angular)路由

我误解了外键的工作原理吗?使用续集

对 google api v3 的 Axios 请求返回加密(?)数据

使用`useLocalStorage`和`useDebounce`时如何解决Next.js中的react-hydration-error

来自 child_process.exec 的错误没有这样的设备或地址,管道有帮助.为什么?

Node.js 大文件上传到 MongoDB 阻塞了事件循环和工作池

分块 WebSocket 传输

按日期时间字段获取最新的 MongoDB 记录

npm install 给出警告,npm audit fix 不起作用

npm WARN 不推荐使用 graceful-fs@3.0.8:graceful-fs 版本 3

expressjs app.VERB 调用中的 next() 和 next('route') 有什么区别?

如何修复此错误 TypeError [ERR_INVALID_CALLBACK]: Callback must be a function