nodejs 的 eval() 会改变 var 关键字的行为吗?

问题描述 投票:0回答:1

所有这些代码片段都在nodejs中运行。

下面是demo1.js,ps:在nodejs而不是浏览器js引擎中运行这些代码

// demo1.js

var1 = 'var1';  // in nodejs or Chrome-V8 js engine, this line would create a property named var1 into globalThis/this/window obj
console.log("[globalThis.var1]:", globalThis.var1);  // var1

globalThis.var2 = 'var2';
console.log('[var2]:', var2);  // var2

var var3 = 'var3';  // in nodejs, this line would not create a property named var3 into globalThis
console.log("[globalThis.var3]:", globalThis.var3);  // undefined

function baz() {
  var var4 = 'var4';  // in nodejs, this line would not create a property named var4 into globalThis
  console.log('[globalThis.var4]:', globalThis.var4);
}
baz();  // undefined

(function () {
  var var5 = 'var5';  // in nodejs, this line would not create a property named var5 into globalThis
  console.log('[globalThis.var5]:', globalThis.var5);
})();

我能理解 demo1.js 中的所有内容。

下面是demo2.js,ps:在nodejs而不是浏览器js引擎中运行这些代码

// demo2.js

(function() {
  (0, eval)("var foo = 123;");  (0, eval)("var foo = 123;");  // indirect call eval,create a property named foo into globalThis, which means create a global scope variable foo.
  (0, function() { console.log('[globalThis.foo]:', globalThis.foo); })();
})();
console.log('[globalThis.foo]:', globalThis.foo);  // 123
console.log('[foo]:', foo);  // 123

在 demo2.js 中,我确实知道逗号运算符会将 eval 执行范围更改为全局范围,并且还根据 直接和间接 eval - MDN 页面
MDN 评估截图

我的问题是:
demo1.js 函数 baz 代码块

var var4 = 'var4'
或 IIFE 代码块
var var5 = 'var5'
,在 nodejs 中这两行不会在 globalThis 中创建属性。
但是demo2.js的IIFE代码块,
var foo = 123
,在nodejs中这一行创建了一个属性到globalThis中。
在 demo1.js 和 demo2.js 中,由于变量都是使用 var 关键字声明的(如 demo1.js 中的
var var4
var var5
,demo2.js 中的
var foo
),为什么 demo2 中只有 var 声明。 js 创建一个属性到 globalThis 中?

javascript node.js scope eval var
1个回答
0
投票

使用 var 进行变量声明: 当您在普通函数或块中使用 var 定义变量时,该变量在该函数或块中变得全面。也就是说,它不会出现在全局作用域或globalThis中。

直接和间接评估: demo2.在js文件中,(0, eval)("var foo = 123;")行使用了eval函数的间接调用。在 JavaScript 中,当间接调用 eval 函数时,它会在全局范围内执行其代码。 特别是,间接 eval 调用会导致 foon 添加到 globalThis 中。

函数作用域demo1.对于js: demo1.js文件中,base()函数和IIFE都没有直接使用eval或逗号运算符。因此,var(var4 和 var5)定义的变量仍然特定于这些函数,不会添加到 globalThis 中。

差异总结

demo1.对于js: var4 和 var5 仍然是本地的,不会添加到 globalThis 中,因为它们是在函数作用域中定义的(在命名函数中或在 IIFE 中)。

demo2.对于js: 由于 eval 函数是由 (0, eval)("var foo = 123;") 间接调用的,因此 foo 定义在全局范围内。这是间接评估的独特行为。

因此,您问题的关键是由于 eval 的调用方式而导致的执行上下文的差异。使用逗号运算符和间接 eval 会导致 foo 在全局作用域中创建,而 demo1.js 中的直接变量声明仍保持其各自函数的作用域。

© www.soinside.com 2019 - 2024. All rights reserved.