如何从new Function()构造函数中获取最后执行的表达式返回值?
实现方案
你要的效果可以通过两种成熟方案实现,均可以规避普通eval的本地作用域访问问题,且能自动返回最后一个表达式的值:
方案1:间接调用全局eval
普通直接调用的eval会绑定当前执行上下文,可以访问本地作用域变量,而间接调用的eval执行上下文为全局,天然无法访问本地作用域,同时默认返回最后一个表达式的值,实现成本极低:
function runREPLCode(code) { // 间接eval调用的固定写法,作用域绑定全局 return (0, eval)(code); } // 测试用例 console.log(runREPLCode('2 + 2;')); // 输出 4 const localVar = 999; console.log(runREPLCode('localVar')); // 全局无该变量时返回undefined,不会拿到本地的localVar
如果要禁用AsyncFunction等特性,可以在执行前先对输入代码做关键字校验,匹配到async、await、function*等非预期关键字直接抛出错误即可。
方案2:完全基于new Function实现
如果完全不想使用eval相关逻辑,可以利用new Function天然绑定全局作用域的特性,搭配简单的代码预处理实现返回最后一个表达式的效果:
function runREPLCode(code) { // 构造全局隔离的执行函数,用内置eval捕获最后返回值,eval仅能访问new Function的全局上下文 const executor = new Function(`return eval(\`${code.replaceAll('`', '\\`')}\`)`); return executor(); }
如果需要处理更复杂的代码场景,也可以引入轻量级JS语法解析库,解析代码的AST找到最后一个表达式节点,手动插入return语句后再传入new Function执行,完全不需要出现eval字样。
进阶安全增强
如果需要更高的执行隔离度,可以搭配sandbox属性的iframe实现完全的上下文隔离,把代码放到独立的iframe环境中执行,彻底和主页面的变量、API隔离开。
内容的提问来源于stack exchange,提问作者Cobertos
相关产品推荐
相关产品推荐

