eval复用当前调用位置的执行上下文,可读写外层变量但不泄露内部声明;new Function仅绑定全局作用域,无法访问外层局部变量。

eval 执行上下文的核心特点
eval 不是独立创建新执行上下文,而是**复用当前调用位置的上下文**。它没有自己的全局对象、作用域链或 this 绑定逻辑,而是直接“嵌入”到调用它的那个函数或全局环境中运行。这意味着:它能读写当前作用域里所有变量(包括 var/let/const 声明的),也能修改外层函数的局部状态,甚至影响闭包行为。
eval 如何访问外层变量
只要变量在调用 eval 的位置是可访问的,eval 内部就能直接使用——不依赖声明方式,也不受块级作用域限制(除非在严格模式下触发 TDZ)。
- 函数内调用 eval → 可访问该函数参数、var/let/const 局部变量
- if 块或 for 循环内调用 eval → 仍可访问所在函数的所有变量(因为块本身不创建执行上下文)
- 在严格模式函数中调用 eval → 仍可访问外层变量,但不能隐式创建全局变量(如未声明就赋值会报错)
eval 定义的变量不会泄露到外层
eval 中用 var/let/const 声明的新变量,只存在于 eval 执行期间的临时词法环境里,执行完即销毁,对外层上下文完全不可见。
示例:
立即学习“Java免费学习笔记(深入)”;
function test() {
eval("var a = 100; let b = 200;");
console.log(a); // ReferenceError: a is not defined
console.log(b); // ReferenceError: b is not defined
}
这和函数执行上下文不同:函数内声明的变量会保留在其变量环境或词法环境中,供整个函数生命周期使用;而 eval 的变量仅限于那一行字符串代码的执行瞬间。
eval 与 new Function 的关键区别
两者都执行字符串代码,但作用域机制截然不同:
- eval:共享调用者的作用域链 → 能访问局部变量、参数、闭包变量
- new Function:只连接全局作用域(或模块顶层)→ 无法访问外层函数的 let/const/var,除非显式传参或挂到 global/window
比如在函数里调用 eval("console.log(x)") 可以正常输出 x 的值;但 new Function("console.log(x)")() 会报 ReferenceError,除非 x 是全局变量。


















