Function构造函数虽可动态创建函数,但存在严重安全风险(如代码注入、绕过CSP)和性能问题(重复解析、无法优化),且破坏静态分析;推荐用配置驱动、模板预编译或沙箱化等更安全方案替代。

Function构造函数能用字符串动态创建函数,但这是把双刃剑——灵活背后藏着严重安全与性能隐患。
Function构造函数的基本用法
它接受任意数量的字符串参数:前面的都是形参名,最后一个为函数体。例如:
const add = new Function('a', 'b', 'return a + b');调用 add(2, 3) 返回 5。它不捕获外层作用域(即没有闭包),所有变量都只能从参数或全局获取,这点和 eval 或箭头函数明显不同。
主要风险:代码注入与执行失控
如果函数体字符串来自用户输入、URL参数、DOM内容或后端响应,就极易触发远程代码执行(RCE)。
立即学习“Java免费学习笔记(深入)”;
- 拼接不可信数据时,攻击者可注入恶意逻辑,比如在表单校验中插入 '; alert(document.cookie); '
- 生成的函数拥有全局执行权限,可能绕过CSP策略(尤其当内联脚本被禁止但 Function 未被明确拦截时)
- 错误处理困难:语法错误发生在运行时,堆栈信息不指向原始源码位置,调试成本高
性能与维护性代价不容忽视
每次调用 new Function 都触发JS引擎重新解析、编译字符串,无法被V8等引擎有效优化或缓存。
- 重复创建相同逻辑的函数会浪费内存,且无法被垃圾回收及时清理(尤其绑定到长生命周期对象时)
- 代码脱离静态分析工具(如ESLint、TypeScript),类型检查、自动补全、重构支持全部失效
- 压缩混淆工具通常无法处理字符串内的代码,导致上线后逻辑裸露、体积增大
更安全的替代方案
多数动态场景其实有更可控的解法:
- 配置驱动逻辑:用数据结构描述行为(如规则数组、状态机定义),再用固定函数解释执行
- 模板函数预编译:借助 template literals + 纯函数组合,避免运行时拼接代码
- 沙箱化执行:确需动态逻辑时,用 iframe、Web Worker 或专用沙箱库(如 vm2)隔离上下文
- 服务端预处理:将动态逻辑前置到构建或API层,返回确定性函数或JSON Schema
除非极特殊场景(如低代码平台的顶层表达式引擎),否则应默认禁用 Function 构造函数。团队可通过 ESLint 规则 no-new-func 主动拦截。


















