【问题标题】:eval black magic loses scopeeval 黑魔法失去作用域
【发布时间】:2017-06-07 20:25:58
【问题描述】:

免责声明我不赞同使用eval,写代码时也不使用。

我在一个遗留项目上分叉逻辑,并在 eval 中遇到了一些非常奇怪的行为,我想知道为什么会存在这种行为的幕后解释。

var baz = function(cb) {
    cb('asdf');
}

function foo(qux, callback) {
    setTimeout(function() {
        // eval(callback('asdf')); // works
        // eval(baz(callback)); // works
        // eval(qux + "(" + callback + ")"); // resolve is undefined
    });
}

function bar() {
    return new Promise((resolve, reject) => {
        try {
            foo('baz', function(response){
                resolve(response);
            });
        } catch (e) {
            reject(e);
        }
    });
}

function init() {
    bar()
    .then(response => {
        console.log(response)
    })
    .catch(e => console.log(e));

}

init();

我写了三个使用 eval 的不同方法的例子,在函数 foo 中注释掉了 第三个例子不起作用。这是我关心的示例,因为它是我们遗留代码的工作方式。我知道还有其他方法可以解决这个问题。我的解决方案是重写函数,完全不使用 eval。

我的问题非常准确,为什么在将函数名作为字符串传入时 eval 会失去作用域,但在传入一个字符串时它不会失去作用域实际引用相同的函数?

这是一个 jsfiddle: https://jsfiddle.net/tkcjay4x/6/

【问题讨论】:

  • 作为 tl;dr 这里:eval 不会“松散范围”。它在当前范围内(直接评估)或全局(在间接评估的情况下)评估代码。

标签: javascript ecmascript-6 eval es6-promise


【解决方案1】:

我不得不承认,这个标题让我有点害怕。如果我理解了这个“黑魔法”,它会让我成为一个邪恶的巫师吗?

当你做eval(baz(callback))时,baz调用callbackeval执行baz的返回值,即undefinedeval(undefined) 等于 eval('undefined') 等于 undefined。所以在这种情况下,使用eval 基本上是无操作的——只使用baz(callback) 会得到相同的结果。

当您执行 eval(qux + "(" + callback + ")") 时,qux + "(" + callback + ")" 的计算结果为 'baz(function(response){ resolve(response); })'。当您将其传递给 eval 时,代码会尝试访问名为 resolve 的函数,该函数不在当前范围内。这就是为什么它不起作用。如果直接调用函数,它可以访问存在于定义它的范围内的变量,但如果将函数转换为字符串并将其传递给eval,它只能访问当前范围内的变量。

【讨论】:

  • 是的,是的。 :)
  • 同意。 eval 是黑暗的艺术。某种西斯尊主的做法。
猜你喜欢
  • 2016-12-05
  • 2015-02-09
  • 2014-05-09
  • 1970-01-01
  • 2016-08-21
  • 1970-01-01
  • 2020-12-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多