Node.js中为何仅间接eval内的var声明会挂载到globalThis?
为什么Node.js中只有间接eval内的var会挂载到globalThis?
核心原因在于eval的调用方式(直接/间接)决定了它的执行作用域,再结合Node.js的模块作用域机制,就导致了这种差异:
1. demo1.js的情况:函数/IIFE内的var不会挂全局
Node.js的每个文件都是一个独立的模块作用域,而非全局作用域:
- 函数
baz内的var var4:变量作用域被严格限制在函数内部,和全局对象完全无关。 - IIFE内的
var var5:IIFE的作用域是模块作用域的子作用域,var声明的变量会提升到模块顶层,但模块作用域的变量不会自动挂载到globalThis——Node.js模块的设计初衷就是隔离全局污染,顶层变量仅在模块内部可见。
示例代码运行结果:
// demo1.js function baz() { var var4 = 'baz'; } (function() { var var5 = 'iife'; })(); console.log(globalThis.var4); // undefined console.log(globalThis.var5); // undefined console.log(var5); // ReferenceError: var5 is not defined
2. demo2.js的情况:间接eval的var会挂全局
根据ECMAScript规范,间接调用eval时,代码会在全局执行上下文中求值,而非当前的函数/模块作用域:
- 间接调用的常见形式:把
eval赋值给变量后调用(var e = eval; e(...))、用call/apply调用、或者在非直接引用eval标识符的场景下调用。 - 在Node.js中,全局执行上下文的变量对象就是
globalThis,所以间接eval里用var声明的变量,会直接成为globalThis的属性。
示例代码运行结果:
// demo2.js (function() { // 间接调用eval const evalFn = eval; evalFn('var foo = 123'); })(); console.log(globalThis.foo); // 123
补充:直接eval vs 间接eval的关键区别
- 直接eval:直接写
eval(...),代码在当前作用域执行。比如在模块的IIFE里直接调用eval('var bar = 456'),bar会成为模块作用域的变量,不会挂载到globalThis。 - 间接eval:任何不直接引用
eval标识符的调用,都会触发全局作用域执行,此时var声明的变量会绑定到全局对象。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

