eval 不该出现在生产代码里,因其导致 v8 放弃优化、破坏作用域稳定性并重走完整编译流程;应以 json.parse 替代 json 解析、new function 替代动态表达式、obj.constructor 创建同类型对象,模板字符串仅用于拼接而非执行。

eval 不该出现在生产代码里——它不是慢一点,而是让 V8 主动放弃优化、破坏作用域稳定性、每次调用都重走完整编译流程。真正要做的,不是“怎么优化 eval”,而是用更安全、更高效的方式替代它。
JSON 解析:直接换掉 eval('('+str+')')
这是最常见也最容易改的误用。很多人用 eval 解析 JSON 字符串,既不安全又慢 8~10 倍。
- ✅ 改成 JSON.parse(jsonString):原生解析,可被 V8 高度优化,支持错误定位
- ⚠️ 注意:JSON 格式必须严格(双引号键名、无 undefined/function),若数据含扩展语法,应统一预处理或换用 MessagePack 等二进制协议
动态表达式:用 new Function 替代 eval
当需要根据字符串生成可执行逻辑(如公式字段、规则引擎),new Function 是 eval 的高性能平替。
- ✅ 它创建独立函数作用域,不污染外层变量,且能被 V8 正常 JIT 编译
- ✅ 支持显式参数传入:const calc = new Function('a', 'b', 'return a * b + 1')
- ⚠️ 切勿拼接用户输入;应先白名单校验运算符和变量名,再构造参数列表
对象重建与类型复用:靠 constructor 属性,别拼类名
想根据一个实例创建同类型新对象?别再写 eval(`new ${obj.constructor.name}()`)——类名可能被压缩、子类继承失效、箭头函数无 constructor。
- ✅ 直接调用:const newInstance = new obj.constructor(...args)
- ✅ 兼容 class 和 function 构造器,天然支持原型链和继承
- ⚠️ 若构造函数有强制参数,由业务层提供默认值或工厂方法兜底,而非依赖字符串拼接
模板字符串 ≠ 动态执行,别混淆概念
模板字符串只是字符串拼接工具,它本身不执行任何代码,也不创建执行上下文。${x + y} 是标准表达式求值,不是 eval 的简化版。
- ❌ 模板字符串中不能写 if、for、return 等语句,也不能动态赋值(如
`x = ${value}`不会改变 x) - ✅ 真正需要“按名取值”时,应显式传入作用域对象:scope[key] 或封装为安全的 lookup 函数











