间接调用eval指非字面量形式调用,如const e=eval;e("...")或(0,eval)("..."),强制在全局作用域执行,无法访问局部变量;直接调用eval("...")则复用当前词法环境。

JavaScript 中 eval 的间接调用,本质是“绕过直接调用语法”,让引擎无法识别为标准的 eval(...) 形式,从而强制其在全局作用域中执行代码,不访问当前函数的局部变量环境。
什么是间接调用
只要不是以 字面量形式 写出 eval(...),就算间接调用。常见方式包括:
- 把
eval赋值给另一个变量后调用,如const myEval = eval; myEval('...'); - 通过属性访问调用,如
window.eval('...')或this.eval('...')(非严格模式下) - 用计算属性或括号语法,如
[eval]()[0]('...')、(0, eval)('...')
间接调用的执行上下文行为
间接调用时,eval 总是在全局执行上下文中运行,无论它出现在多深的函数嵌套里:
- 无法读取或修改外层函数的
let、const、var局部变量 - 声明的变量(如
var z = 1)会挂到全局对象上(浏览器中是window.z) - 在严格模式下,间接
eval仍不能访问局部变量,但也不会污染全局——新声明的var不会成为全局属性(ES2015+ 行为)
和直接调用的关键对比
同一段代码,在不同调用方式下表现完全不同:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
立即学习“Java免费学习笔记(深入)”;
function test() {
const localVar = 'inside';
eval('console.log(localVar)'); // ✅ 直接调用:能输出 'inside'
(0, eval)('console.log(localVar)'); // ❌ 间接调用:报错 ReferenceError
}这是因为直接调用复用了当前函数的词法环境,而间接调用丢弃了该环境,只保留全局作用域链。
为什么这很重要
间接调用不是“更安全”的替代方案,而是改变了作用域规则:
- 它不能解决
eval的核心问题:字符串代码不可静态分析、易被注入、性能差 - 它可能掩盖 bug——比如你以为变量能被访问,结果因间接调用而失效
- 现代工具(如 ESLint)通常对所有
eval调用统一警告,不区分直接/间接

















