Function构造函数虽可动态创建函数,但存在代码注入、CSP绕过等安全风险,性能开销大且无法访问外层作用域变量;推荐用配置驱动、模板预编译或沙箱化方案替代。

Function构造函数可以动态创建函数,但不推荐用于执行任意字符串代码——它有安全风险、性能开销,且无法访问当前作用域的变量。
Function构造函数的基本用法
它接受参数名(字符串)和函数体(字符串),返回一个新函数:
- 第一个到倒数第二个参数是形参名(每个都是字符串)
- 最后一个参数是函数体代码(字符串)
- 返回的是一个普通函数,可立即调用或保存复用
例如:const add = new Function('a', 'b', 'return a + b');
调用 add(2, 3) 返回 5。
与eval的区别:作用域更受限
Function构造函数创建的函数总在全局作用域中执行,无法读取外层函数的局部变量:
- eval('console.log(x)') 能访问当前作用域的 x
- new Function('console.log(x)')() 会报错 ReferenceError: x is not defined
这是它比 eval 稍安全的地方,但也意味着不能靠它“注入”局部逻辑。
立即学习“Java免费学习笔记(深入)”;
常见误用场景及替代方案
有人想用它实现模板计算、配置驱动逻辑或简易表达式求值,但存在隐患:
- 用户输入拼进字符串 → XSS 或代码注入(如 new Function('return ' + userInput)())
- 频繁调用 → 每次都重新解析字符串,性能差
- 调试困难 → 报错堆栈指向匿名函数,无源码映射
更稳妥的做法:
• 表达式计算用 Function 前先白名单校验或用专用库(如 math.js)
• 配置驱动行为用对象映射或策略模式
• 动态逻辑优先考虑闭包 + 参数化函数,而非拼字符串
真需要动态函数时的注意事项
如果业务确实绕不开(比如低代码平台的简单公式编译),至少做到:
- 严格过滤输入:只允许数字、运算符、预定义变量名和括号
- 限制执行时间:用 setTimeout 或 Promise.race 加超时控制
- 捕获异常:始终用 try...catch 包裹调用,不暴露内部错误
- 避免闭包依赖:所有数据必须显式传入参数,不要指望外部变量
例如:const calc = new Function('a', 'b', 'op', 'return op === "+" ? a + b : op === "-" ? a - b : 0');


















