【问题标题】:new Function() return last value?new Function() 返回最后一个值?
【发布时间】:2021-11-12 07:58:07
【问题描述】:

如何从new Function() 构造函数返回最后一个值?似乎 eval() 默认会这样做,vm.Script#runInContext 也是如此。

我只想在浏览器中创建一个 REPL(我可以在其中执行 2+2; 之类的操作,并在输出中返回 4),例如 eval,但没有 eval 的缺点(本地函数范围访问,AsyncFunction,等等...)

【问题讨论】:

  • 您正在寻找completion record 的值。据我所知,除了使用 evalnew Function 或类似的东西之外,这些在 JS 脚本或模块中是无法观察到的。
  • eval 经常得到一个坏名字,是的,它有安全问题,但在你的情况下,用户正在处理请求,并且没有说它被代理,因为那会很糟糕。我还要说new Function 无论如何都会有同样的问题。
  • @SebastianSimon 嗯,是的,这就是我要找的。我不介意使用new Function,只是想避免使用eval()。似乎new Function 只是不支持它?所以我必须做类似eval('(async function(){ ' + input + ' })()') 的事情,因为REPL 还需要支持带有awaits 的异步代码
  • 查看ECMAScript伪代码后,看来这只是Function对象的限制。整个部分只提到一次Completion(所以没有真正的方法可以访问函数的完成记录)。但这是 eval() 确实返回的东西,如规范中所定义。所以我猜 eval 是唯一的方法

标签: javascript eval function-constructor


【解决方案1】:

您可以使用Web Worker 在隔离范围内运行某些东西。在那里,您可以安全地使用eval,而不必担心访问页面的局部范围变量。试试这样的:

function run() {
  const code = `
  self.onmessage = async (evt) => {
    let result;
    try {
      result = await eval(evt.data);
    } catch(err) {
      result = 'Error: ' + err.message;
    }  
    self.postMessage(result);
  };
  `;
  const blob = new Blob([code], {
    type: "text/javascript"
  });
  const worker = new Worker(window.URL.createObjectURL(blob));
  worker.onmessage = function(e) {
    document.getElementById('out').value = e.data;
  }
  worker.postMessage(document.getElementById('repl').value);
}
<label for="repl">REPL:</label>
<input type="text" id="repl">
<button onclick="run()">Execute</button>
<p/>
<label for="out">Output:</label>
<input type="text" id="out" readonly>

灵感来自this 答案:)

【讨论】:

  • 哦,我从来没有想过这个。这是个好主意!
【解决方案2】:

没有办法做到这一点。

根据ECMAScript specification part on Function objectsnew Function() 不提供任何访问"Completion Records" 的方法。

所以如果你需要最后一个值,你必须使用eval()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    • 2017-02-09
    • 2018-02-22
    • 1970-01-01
    • 2021-12-14
    相关资源
    最近更新 更多