全局变量分配节点从脚本vs命令行

global variable assignment in node from script vs command line

本文关键字:vs 命令行 脚本 分配 节点 全局变量      更新时间:2023-09-26

我有以下脚本:

/* script.js */
var bar = "bar1";
function foo() {
    console.log('this.bar: ' + this.bar);
    console.log('global.bar: ' + global.bar);
}
foo();

运行node script.js返回:

this.bar: undefined
global.bar: undefined

但是,在节点命令行环境中,复制相同的脚本将返回:

this.bar: bar1
global.bar: bar1

此外,如果我将变量声明从var bar = "bar1";更改为global.bar = "bar1";,则运行上述代码的两个方法都返回:

this.bar: bar1
global.bar: bar1

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

原因很简单,因为每个节点模块都被封装在IIFE中,所以默认情况下你不在全局作用域中。

我们可以看到它发生在src/node.js中,在NativeModule函数中。

NativeModule.require = function(id) {
    // ...
    var nativeModule = new NativeModule(id);
    nativeModule.cache();
    nativeModule.compile();
    return nativeModule.exports;
};

根据线索,我们查看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;
};

wrap看起来很相关,让我们看看它是怎么做的:

NativeModule.wrap = function(script) {
    return NativeModule.wrapper[0] + script + NativeModule.wrapper[1];
};
NativeModule.wrapper = [
    '(function (exports, require, module, __filename, __dirname) { ',
    ''n});'
];

正如所怀疑的那样,它将模块的代码包装在IIFE中,这意味着您不会在全局作用域中运行。

另一方面,REPL默认在全局作用域中运行。遵循REPL代码是不错的,但它基本上归结为这一行:

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

这看起来和我很相关

http://nodejs.org/api/globals.html

var某个Node模块中的东西将是该模块的本地内容。

我认为当你从文件中运行一些东西时,它被解释为节点的模块。如果在命令行中执行,则作用域顶部的变量变为全局