从脚本到命令行的节点中的全局变量赋值

mon*_*ers 11 javascript node.js

我有以下脚本:

/* script.js */
var bar = "bar1";

function foo() {
    console.log('this.bar: ' + this.bar);
    console.log('global.bar: ' + global.bar);
}
foo();
Run Code Online (Sandbox Code Playgroud)

运行node script.js回报:

this.bar: undefined
global.bar: undefined
Run Code Online (Sandbox Code Playgroud)

但是,从节点命令行环境内部,再现相同的脚本将返回:

this.bar: bar1
global.bar: bar1
Run Code Online (Sandbox Code Playgroud)

另外,如果我改变从我的变量声明var bar = "bar1";global.bar = "bar1";运行上面的代码返回的两种方法:

this.bar: bar1
global.bar: bar1
Run Code Online (Sandbox Code Playgroud)

有什么不同?运行脚本与在同一环境中重现脚本时,全局变量赋值是否有所不同?

Zir*_*rak 5

仅仅因为每个节点模块都包装在某种IIFE中,所以默认情况下您不在全局范围内。

我们可以src/node.jsNativeModule函数的中看到它的发生。

NativeModule.require = function(id) {
    // ...
    var nativeModule = new NativeModule(id);

    nativeModule.cache();
    nativeModule.compile();

    return nativeModule.exports;
};
Run Code Online (Sandbox Code Playgroud)

沿着足迹,我们调查compile

NativeModule.prototype.compile = function() {
    var source = NativeModule.getSource(this.id);
    source = NativeModule.wrap(source);

    var fn = runInThisContext(source, { filename: this.filename });
    fn(this.exports, NativeModule.require, this, this.filename);

    this.loaded = true;
};
Run Code Online (Sandbox Code Playgroud)

wrap 看起来很相关,让我们看看它的作用:

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

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

令人怀疑的是,它将模块的代码包装在IIFE中,这意味着您不在全局范围内运行。

另一方面,默认情况下,REPL 在全局范围内运行。遵循REPL代码的是meh,但基本上可以归结为这一行

if (self.useGlobal) {
    result = script.runInThisContext({ displayErrors: false });
} else {
    result = script.runInContext(context, { displayErrors: false });
}
Run Code Online (Sandbox Code Playgroud)

看起来与我无关。