为何大厂内部都禁用了这个 JavaScript 特性?


有一个 JavaScript 特性经常被明确禁止使用—— eval()
函数及其变体。这个看似强大的特性为何会被微软、谷歌、Facebook等顶级公司列入黑名单?

eval():强大而危险的双刃剑

eval() 函数可以将字符串作为JavaScript代码执行,看起来可以实现许多动态功能:

const expr = 'var x = 10; x * 2';  
eval(expr); // 返回 20  

然而,这种动态执行代码的能力带来了严重的安全风险和性能问题。

安全隐患:注入攻击的温床

最严重的问题是安全风险。当 eval() 与用户输入结合时,它成为代码注入攻击的完美载体:

攻击者可以通过这种方式:

  • 窃取敏感数据
  • 执行恶意操作
  • 劫持用户会话
  • 修改页面内容

性能问题:V8引擎的噩梦

JavaScript引擎无法优化包含 eval() 的代码,因为:

  1. 阻碍编译优化:使用 eval() 的函数无法被预编译
  2. 禁用内联缓存:包含 eval() 的作用域链必须保持动态
  3. 强制变量查找变慢:编译器无法确定变量引用,必须进行动态解析

Chrome V8团队的内部测试显示,含有 eval() 的代码执行速度可能慢至少10倍。

可维护性:代码审计的盲点

使用 eval() 的代码:

  • 难以调试(堆栈跟踪不清晰)
  • 增加代码复杂性
  • 降低静态分析工具的有效性
  • 使代码审计变得困难

执行上下文污染

eval() 在当前作用域内执行代码,可能意外修改或覆盖变量:

大厂的应对策略

Google的JavaScript风格指南明确表示:

“不要使用eval()。它使代码容易受到注入攻击,并且使JavaScript引擎难以进行优化。”

微软的安全编码准则规定:

“禁止使用eval()和Function构造函数,除非有经过严格审核的特殊需求。”

大多数大厂采取的措施包括:

  1. 严格的ESLint规则禁用eval
  2. 代码审查中将eval使用标记为严重问题
  3. 提供安全的替代API
  4. 安全扫描工具自动识别eval的使用

替代方案

对于大多数使用eval()的场景,都存在更好的替代方案:

1. 使用JSON.parse替代解析数据

2. 使用对象映射替代动态访问

3. 使用新的API替代动态计算

// 不要这样做  
const result = eval('2 * 3 + 4');  
  
// 改用这种方式  
const result = new Function('return 2 * 3 + 4')();  
// 或更好的方式,使用专门的表达式解析库