eval在当前作用域执行,可访问并修改外层局部变量;new Function创建隔离的全局作用域,仅能访问全局变量和显式参数,安全性更高。

eval 和 new Function 都能执行字符串形式的 JavaScript 代码,但它们创建和使用执行上下文的方式完全不同——这直接决定了谁能访问变量、谁会污染作用域、谁更难被攻击。
eval 在当前作用域中执行
eval 不新建执行上下文,而是复用调用它的那一层上下文。它能读写外层函数的局部变量、块级变量,甚至修改 let/const 声明的绑定(在非严格模式下还能用 var 动态声明变量)。
- 在函数内部调用 eval,它就能访问该函数所有局部变量
- 嵌套多层函数时,eval 仍沿作用域链向上查找,可触及父级、祖父级变量
- 直接调用(如
eval('...'))才进入当前作用域;间接调用(如eval.call(null, '...'))则降级到全局作用域
new Function 总是隔离在全局作用域
new Function 每次都创建一个全新函数对象,其执行上下文的作用域链只包含全局对象(或模块顶层),完全不继承调用位置的局部环境。
- 即使在 deeply nested 函数里构造 new Function,它也看不到任何外层 let/const 变量
- 只能访问全局变量、浏览器内置对象(如 window、document)、以及显式传入的参数
- 函数体默认是非严格模式,如需严格模式,必须手动写
"'use strict'; ..."
安全边界差异明显
eval 的“透入性”是双刃剑:方便调试和动态逻辑,但也意味着恶意字符串可直接篡改业务状态、窃取用户数据、注入脚本。new Function 虽不能绕过同源策略,但天然隔绝了局部敏感信息。
- 用户可控输入若拼进 eval 字符串,可能执行任意代码并访问当前页面所有 JS 状态
- new Function 至少无法读取闭包内 token、表单值、临时计算结果等关键局部数据
- 两者都不应处理不可信输入,但 new Function 的攻击面更窄、更易沙箱化
实际使用中的关键细节
别只看“能运行”,要盯住变量来源和副作用范围。比如解析 JSON 或表达式时,写法稍有不同,行为就大不一样。
- eval 解析对象字面量需加括号:
eval('(' + jsonStr + ')'),否则 {} 被当代码块处理 - new Function 返回函数,必须显式 return 并调用:
new Function('return ' + expr)() - 想让 new Function 访问某些值?只能靠参数传入,不能依赖词法作用域
- 性能上 new Function 略慢于 eval,但现代引擎优化后差距不大;安全收益远高于这点开销

















