2012-10-30 47 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

只想確認在鉻中,查理所說的是正確的。在使用調試器語句時,我需要在閉包中使用它之前,對所討論的變量進行引用!