javascript - 上下文保留评估

标签 javascript scope eval

我们正在构建一个小型 REPL,它会在用户输入时评估(使用 eval )javascript 表达式。由于整个事情是事件驱动的,因此评估必须在单独的函数中进行,但必须在调用之间保留上下文(即所有声明的变量和函数)。我想出了以下解决方案:

function* _EVAL(s) {
    while (1) {
        try {
            s = yield eval(s)
        } catch(err) {
            s = yield err
        }
    }
}

let _eval = _EVAL()
_eval.next()

function evaluate(expr) {
    let result = _eval.next(expr).value
    if (result instanceof Error)
        console.log(expr, 'ERROR:', result.message)
    else
        console.log(expr, '===>', result)
}

evaluate('var ten = 10')
evaluate('function cube(x) { return x ** 3 }')
evaluate('ten + cube(3)')
evaluate('console.log("SIDE EFFECT")')
evaluate('let twenty = 20')
evaluate('twenty + 40') // PROBLEM

如您所见,它适用于函数范围的变量( varfunction ),但在 block 范围的变量( let )上失败。
我怎样才能写一个保留上下文的 eval也可以保留 block 范围变量的包装器?
代码在浏览器中运行,DOM 和 Workers 完全可用。
应该提到的是,所需的函数必须正确处理副作用,即每一行代码,或者至少每个副作用,应该只执行一次。
链接:
JavaScript: do all evaluations in one vm | https://vane.life/2016/04/03/eval-locally-with-persistent-context/

最佳答案

article you linked包含一个实际有效的疯狂方法:在每个 eval() 期间调用,我们在 eval 内部创建一个新的闭包范围并将其导出,以便我们可以使用它来评估下一条语句。

var __EVAL = s => eval(`void (__EVAL = ${__EVAL.toString()}); ${s}`);

function evaluate(expr) {
    try {
        const result = __EVAL(expr);
        console.log(expr, '===>', result)
    } catch(err) {
        console.log(expr, 'ERROR:', err.message)
    }
}

evaluate('var ten = 10')
evaluate('function cube(x) { return x ** 3 }')
evaluate('ten + cube(3)')
evaluate('console.log("SIDE EFFECT")')
evaluate('let twenty = 20')
evaluate('twenty + 40') // NO PROBLEM :D

关于javascript - 上下文保留评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67322922/

相关文章:

jquery - Firefox 操作系统特权应用程序错误 : call to eval() blocked by csp at jquery 1. 9.1

javascript - Firebase数据重复问题

javascript - Angular : If-operations on $scope. 变量

java - 为什么 Java 中的 switch 语句的范围没有限制?

eval - 如何在 JavaScript 命令中使用变量?

java - Android Expj4 检查表达式是否无效

javascript - 带有点击的 jQuery load() 动态内容被触发的次数与加载的次数一样多

javascript - 如何在 jquery 中将链接转换为 seo 友好的 url

javascript - 样式滚动条仅适用于 div,不适用于整个主体

javascript - Node.js 变量声明和范围