如何在eval中不使用this关键字调用非全局作用域的JS函数
解决方案
核心需求实现(无需this调用函数)
你遇到的报错原因是eval执行时作用域无法访问到类内部导入的isValidDocument变量,推荐使用更可控的new Function方案实现无this调用:
import isValidDocument from './isValidDocument' class Test { execute(person) { // 从数据库读取用户自定义表达式 const userExpression = 'isValidDocument(person) && person.age > 18' // 定义函数形参,把需要暴露给表达式的变量/函数都作为形参传入 const runRule = new Function('isValidDocument', 'person', `return ${userExpression}`) // 执行时传入对应实参即可 const evalResult = runRule(isValidDocument, person) console.log("Eval Result:", evalResult) } }
如果一定要用eval实现,也可以在当前作用域先解构出需要用到的函数:
execute(person) { const { isValidDocument } = this const evalResult = eval('isValidDocument(person)') }
该方案不推荐,因为eval可以访问当前作用域所有变量,风险远高于new Function。
执行环境隔离安全建议
开放用户自定义JS表达式权限前,建议按优先级落实以下安全措施:
- 优先使用
new Function替代直接eval:new Function的运行作用域仅包含全局环境和你主动传入的参数,不会泄露当前执行上下文的局部变量 - 严格白名单控制暴露的API:仅传入表达式需要用到的函数和参数,禁止暴露全局对象、内部业务方法、数据库操作接口等敏感能力
- 屏蔽全局敏感对象:创建函数时把所有全局敏感对象作为形参传入并赋值为
undefined,避免用户访问:const runRule = new Function( 'isValidDocument', 'person', 'window', 'global', 'process', 'fetch', 'Function', 'constructor', '__proto__', `return ${userExpression}` ) const evalResult = runRule(isValidDocument, person, ...new Array(7).fill(undefined)) - 后端执行时用原生隔离能力:如果是Node.js后端执行规则,直接使用
vm模块执行代码,设置超时时间避免死循环卡服务:const vm = require('vm') // 创建完全隔离的上下文 const context = vm.createContext({ isValidDocument, person }) // 超时时间设为100ms,超过直接终止执行 const evalResult = vm.runInContext(`return ${userExpression}`, context, { timeout: 100 }) - 表达式语法校验:执行前先把用户表达式解析为AST,检查禁止的语法(赋值语句、函数定义、原型链访问等),不符合规则直接拒绝执行
- 敏感逻辑统一后端执行:前端执行的规则结果仅做展示使用,涉及权限、数据校验的核心逻辑必须在后端二次校验,避免前端篡改绕过规则
内容的提问来源于stack exchange,提问作者user12227125
相关产品推荐
相关产品推荐

