【问题标题】:variable undefined in closure?闭包中未定义的变量?
【发布时间】:2012-10-20 06:02:15
【问题描述】:

我有这样的功能:

function foo(canvas) {
    canvas.mousedown(function(e) {
        console.log(canvas); //undefined
    });
}

我在页面的某个位置单击鼠标时调用 foo。

为什么画布未定义?

【问题讨论】:

  • 你给foo传递了一个参数吗?
  • 嗯...是的,jsfiddle 有效。我的代码更复杂,看看还有什么可能导致问题...
  • canvas 应该从不在回调中评估为 undefined。 canvas 变量 不能 在提供的代码中重新分配(对象被变异是另一回事),并且 那个特定的 console.log 只有在 @987654327 时才会运行@ 是有效的(这意味着 canvas 不是未定义)。因此,我称之为恶作剧。报告的行为要么是错误的,要么不是全部。
  • @TML 和其他人:在 FF 中对我来说效果很好。它有助于在画布上设置背景颜色,这样你就可以看到该死的东西!
  • 在 Win32 上的 Chrome 和 Firefox 中对我来说都很好。您使用的是哪个版本的 Chrome?你真的点击了画布吗? SnagIt Screenshot of Chrome result

标签: javascript jquery variables closures


【解决方案1】:

调试器可能不会在闭包中显示变量,直到它们被使用。

考虑这个例子,其中定义了 a 变量但从未使用过:

(function() {
  var x = 1;
  $(function () {
    debugger; // debugger stopped here, `x` is `undefined` in Chrome and IE but `1` in Firefox
    console.log("hi");
  }
})();

相同的代码,除了变量被打印出来而不是字符串文字:

(function() {
  var x = 1;
  $(function () {
    debugger; // debugger stopped here, all three browsers show `x` as `1`
    console.log(x);
  }
})();

【讨论】:

    【解决方案2】:

    问题是这样的:

    function foo(canvas) {
        canvas.mousedown(function(e) {
            console.log(canvas); //undefined
            //...
            for (var i in array) {
                var canvas = array[i].canvas;
                //...
            }
        });
    }
    

    我没有时间调查确切的原因。我的猜测是编译器在匿名函数的开头放置了一个“var canvas”声明,这样在控制台中输出时变量是未定义的。不然还不明白。

    【讨论】:

    • 这是一个绝妙但被低估的答案,它揭示了一些关于变量作用域的隐藏行为和复杂性。还有一种情况,使用ES6 中的let canvas = ... 也可以!
    【解决方案3】:

    一旦你给出了整个代码示例,你自己的答案就是正确的。您遇到了称为“变量提升”的 Javascript 怪癖。您的代码被解释为:

    function foo(canvas) {
        canvas.mousedown(function(e) {
            var i, canvas; //variable declarations moved to top of function scope
            console.log(canvas); //undefined
            //...
            for (i in array) {
                canvas = array[i].canvas;
                //...
            }
        });
    }
    

    见:

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#var_hoisting

    http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html

    【讨论】:

    • 对,这就是问题的答案和原因!它帮助我解决了这个问题,谢谢。
    【解决方案4】:

    只想确认在 chrome 中,查理所说的是正确的。在使用调试器语句时,我需要先引用相关变量,然后才能在闭包中使用它!

    【讨论】:

      猜你喜欢
      • 2012-11-03
      • 2017-05-11
      • 2019-04-17
      • 1970-01-01
      • 2017-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多