所有这些代码片段都在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 中创建属性。var foo = 123
,在nodejs中这一行创建了一个属性到globalThis中。var var4
和 var var5
,demo2.js 中的 var foo
),为什么 demo2 中只有 var 声明。 js 创建一个属性到 globalThis 中?
使用 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 中的直接变量声明仍保持其各自函数的作用域。