2012-10-30 54 views
4

我有这样的功能:变量在闭包中未定义?

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

,我号召鼠标点击FOO在页面的某个地方。

为什么canvas未定义?

+0

您是否通过了'foo'参数? – SLaks

+0

'.mousedown'应该是'.onmousedown',否? –

+0

@SLaks你的意思是一个参数,而不是参数。 – Rayshawn

回答

2

的问题是这样的:

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

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

+1

这是一个辉煌和低估的答案,揭示了一些隐藏的行为和变量范围的复杂性。还有一种情况是使用[ES6]中的'let canvas = ...'(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let)可以工作! – hughes

2

你自己的答案是正确的,一旦你给了整个代码示例。你遇到了一个被称为“变量提升”的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

+0

对,这就是问题的答案和原因!它帮助我解决它,谢谢。 –

10

调试器可以在不关闭显示变量,直到它们被使用。

考虑这个例子,其中一个变量被定义但从未使用:

(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); 
    } 
})(); 
0

只想确认在铬中,查理所说的是正确的。在使用调试器语句时,我需要在闭包中使用它之前,对所讨论的变量进行引用!