Node.js 启动方式:一道关于全局变量的题目引发的思考·续

465 查看

本文是上文《Node.js 启动方式:一道关于全局变量的题目引发的思考》的续章。

原题回顾

我们还是先回顾下原题吧。

上题由我们亲爱的小龙童鞋发现并在我们的 901 群里提问的。

不过在上面一篇文章中,我们讲的是在 REPL 和 vm 中有什么事情,但是并没有解释为什么在文件模块的载入形式下,var 并不会挂载到全局变量去。

其实原因很简单,大家应该也都明白,在 Node.js 中,每个文件相当于是一个闭包,在 require 的时候被编译包了起来。

但是具体是怎么样的呢?虽然网上也有很多答案,我还是决定在这里按上一篇文章的尿性稍微解释一下。

分析

首先我们还是回到上一篇文章的《Node REPL 启动的沙箱》一节,里面说了当启动 Node.js 的时候是以 src/node.js 为入口的。

如果以 REPL 为途径启动的话是直接启动一个 vm,而此时的所有根级变量都在最顶级的作用域下,所以一个 var 自然会绑定到 global 下面了。

而如果是以文件,即 $ node foo.js 形式启动的话,它就会执行 src/node.js 里面的另一坨条件分支了。

从上面的代码看出,只要是以 $ node foo.js 形式启动的,都会经历 startup.preloadModules() 和 Module.runMain() 两个函数。

startup.preloadModules()

我们来看看这个函数

实际上就是执行的 lib/module.js 里面的 _preloadModules 函数,并且把这个 process._preload_modules 给传进去。当然,前提是有这个 process._preload_modules

process._preload_modules

这个 process._preload_modules 指的就是当你在使用 Node.js 的时候,命令行里面的 --require 参数。

代码在 src/node.cc 里面可考。