【问题标题】:Javascript variable captureJavascript变量捕获
【发布时间】:2016-09-17 20:06:29
【问题描述】:

我在 JS 中使用 eval 时遇到了奇怪的行为。

var f = function () {
    var x = 10;

    return function () {
        eval('console.log(x);');
        window['eval']('console.log(x);');
    }
};

f()();

输出:

10
undefined:1
console.log(x);
            ^
ReferenceError: x is not defined

为什么使用eval 显式捕获xglobal['eval'] 没有? 而且即使global['eval']没有捕捉到x,为什么在已经捕捉到xeval之后就看不到了?

【问题讨论】:

  • 更好的问题是你为什么使用 eval? eval 做神奇的事情。最好别管它。
  • 有时为了远程测试,我需要快速加载和运行我的本地代码。不适用于生产代码:)
  • @NehalJWani 不相关,问题是关于使用eval 时的捕获。谢谢。
  • “有时对于远程测试,我需要快速加载并运行我的本地代码” - 然后我建议您找到更好的方法来做到这一点。您已经无法理解现在正在发生的事情,因此在以这种方式进行测试时,您很可能会再次遇到此类或类似的行为 - 因此您将永远无法快速确定问题出在您的实际代码上,还是仅与你让它执行的方式。我宁愿使用调试工具,让我的生活更轻松,而不是更难。

标签: javascript eval


【解决方案1】:

window['eval'] 在全局范围内运行,eval() 在本地范围内运行。

来自 Mozilla 的 Javascript 参考:

如果你间接使用 eval 函数,通过调用它 eval 以外的参考,从 ECMAScript 5 开始,它在全局范围内工作 而不是本地范围;这意味着,例如,该功能 声明创建全局函数,并且代码正在 评估无权访问范围内的局部变量 它被调用的地方。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval

【讨论】:

    【解决方案2】:

    您的内部函数实际上并没有捕获x 的引用,因此它永远不会直接传递给eval

    eval 通常工作 at the local scope,所以第一次调用成功(因为本地范围包含 x 的声明)。

    但是,如果您以没有直接引用的方式调用 eval,它将在var x 不属于的全局范围内调用自身,并且它会失败。

    只是不要使用 eval。

    【讨论】:

      【解决方案3】:

      您可以使用Function.prototype.bind()x 传递给返回函数

      var f = function () {
          var x = 10;
      
          function y(n) {
              eval(`console.log(${n})`);
              window["eval"](`console.log(${n})`);
          }
      
          return y.bind(this, x)
      };
      
      f()();

      【讨论】:

      • 嗯,这是字符串插值,你甚至不需要为此绑定,你可以直接在 eval 语句中插入变量而不使用参数。 f = function() { var x = 5; return function () { eval(`console.log(${x})`) } }
      【解决方案4】:

      window.eval 在全局范围内工作。

      var variable = 1;
      
      (function(){
        var variable = 100,
            cmd = "++variable";
        document.write(eval(cmd)+"\n"); // increment local var 100 and output 101
        document.write(window.eval(cmd)+"\n"); // increment global var 1 and output 2
      })();

      【讨论】:

        猜你喜欢
        • 2021-02-08
        • 2012-04-23
        • 2021-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-12
        相关资源
        最近更新 更多