eval() 几乎不该被使用,因其将字符串当作代码执行,易受用户输入等不可信源攻击,导致XSS、凭证窃取等安全问题,且阻碍代码优化与调试;应改用JSON.parse()、方括号属性访问、mathjs等安全替代方案。

eval() 是 JavaScript 中一个能执行字符串代码的函数,但它在现代开发中几乎不该被使用——不是因为它不能用,而是因为风险远大于收益。
eval() 的基本行为和典型误用场景
它接收一个字符串参数,将其当作 JavaScript 代码解析并执行,返回最后一条语句的值(或 undefined)。
常见误用包括:动态拼接对象属性名、从后端取 JSON 字符串后直接 eval() 解析、实现简易表达式计算器等。
- 它不区分“数据”和“代码”,任何传入的字符串都会被完整执行
- 作用域继承自调用位置(非全局),但依然可访问闭包内变量和外部函数
- 无法被 JS 引擎静态分析,影响压缩、混淆、Tree-shaking 和 DevTools 调试
为什么 eval() 容易引发严重安全问题
核心在于:一旦字符串内容来自用户输入、URL 参数、localStorage、第三方 API 或未严格校验的配置项,就等于把执行权交给了攻击者。
立即学习“Java免费学习笔记(深入)”;
例如,某页面通过 URL 的 callback 参数构造回调:
eval('handle(' + location.search.match(/callback=([^&]+)/)[1] + ')'); 攻击者只需访问 https://site.com/?callback=alert(1)// 即可弹窗;更进一步,callback=console.log(document.cookie)// 就可能窃取凭证。
- 绕过 CSP(Content Security Policy)策略:即使禁用了
unsafe-eval,某些旧版浏览器或配置疏漏仍可能让eval()生效 - 无法做语法沙箱隔离:不像
Web Workers或iframe sandbox,eval()运行在当前上下文,拥有全部权限 - 错误堆栈模糊:报错时指向
eval调用处,而非真实出错的字符串内部位置
有哪些更安全的替代方案
绝大多数 eval() 使用场景都有标准、可控的替代方式。
- 解析 JSON:永远用
JSON.parse(),它只接受合法 JSON 格式,拒绝执行任意代码 - 动态访问对象属性:用方括号语法
obj[propertyName],配合白名单校验(如if (['name', 'email'].includes(key)) { ... }) - 执行数学表达式:用专门库如
mathjs.eval()或正则+运算符分步解析,避免全字符串求值 - 模板渲染:用
template literals、Handlebars等模板引擎,它们默认转义输出且不执行逻辑代码
如果真要保留 eval()(极少数遗留系统),至少做到三点
这不是推荐做法,而是给无法立即重构的系统兜底的最低防线。
- 确保输入字符串完全由可信源生成(如硬编码常量、构建时生成的配置),且不含任何运行时拼接
- 用正则提前过滤危险模式:比如禁止出现
;、function、return、document、eval、new Function等关键词 - 在
try/catch中包裹调用,并限制超时(需配合Worker或setTimeout模拟,原生eval不支持中断)
真正难的不是写一行 eval(),而是判断字符串里有没有隐藏的 __proto__.constructor.constructor 链式调用——这种细节在代码审查中极易被忽略。










