位置:首页 > JavaScript > JavaScript中如何理解eval执行的动态作用域与作用域污染

JavaScript中如何理解eval执行的动态作用域与作用域污染

时间:2026-08-12  |  作者:火苗实验室  |  阅读:0

很多人容易把 eval 误会成“动态作用域”,其实并不是这么回事。它更像是直接闯进当前的词法作用域里,对里面的变量进行读取和写入,因此很容易造成作用域污染;它并不会沿着作用域链去查找,但照样可以改动外层的let/const/var变量,甚至还能声明新变量,并把这些变量泄漏到函数顶层。相比之下,Function构造函数自带独立作用域,隔离性会更强。

Ja vaScript 中怎么理解 eval 执行时的动态作用域与污染

很多人会把 eval 的执行效果误读成“动态作用域”,但实际并不是这么回事。

它真正依赖的,是当前词法作用域的快照;同时,它又会直接去读取和改写这个作用域里的变量。

也正因为这样,看上去像是作用域在“动态变化”,可本质上,这其实是作用域污染

eval 的本质:进入当前词法作用域

eval 怎么访问变量:不是查找,而是“闯入”

eval 不像函数调用那样遵循作用域链逐层向上找。

它在执行时,就站在调用它的那个函数内部,能直接看到、修改所有局部变量和外层闭包变量:

  • 在函数里调用 eval,它就能读写该函数的所有 letconstvar 变量
  • 如果函数嵌套,eval 还能访问外层函数的变量(只要没被遮蔽)
  • 它甚至能声明新变量:eval("var x = 100"),这个 x 就会出现在当前作用域中

作用域污染体现在哪里

污染的具体表现:变量被悄悄改写或泄漏

这种“闯入”能力会导致两类常见污染,另外还会影响引擎优化:

  • 意外覆盖:比如你写了 let count = 5,eval 里执行 "count = count * 2",外部的 count 立刻变成 10
  • 变量泄漏:用 var 声明的变量会提升到函数顶层,eval("var temp = 'hello'")temp 在整个函数内都可访问
  • 破坏优化:V8 引擎一旦发现函数里有 eval,就会禁用大部分 JIT 优化,因为无法静态确定变量是否被改过

eval 与 Function 构造函数的区别

和 Function 构造函数的关键区别

很多人用 new Function(...) 替代 eval,因为它不污染当前作用域。

  • new Function('x', 'return x + 1') 创建的函数,只认自己参数和全局变量,完全看不到外层函数的 let y = 2
  • 它有自己的独立作用域,不会修改调用位置的任何变量
  • 虽然仍不安全(执行任意代码),但至少做到了作用域隔离

更安全的处理方式

真正安全的做法:别让 eval 接触敏感上下文

如果非得用字符串执行逻辑,优先考虑以下做法:

  • Function 构造函数传参建沙盒,把所需变量显式当参数传进去
  • 对输入脚本做白名单校验(比如只允许数字、运算符、括号和已知变量名)
  • 绝对不要把 windowdocumentlocalStorage 或带原型的对象放进执行环境
  • JSON 解析一律用 JSON.parse(),永远不用 eval('(' + json + ')')

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多