2014-01-16 44 views
0

我目前的工作在一個相對簡單的項目,發現了一些:Javascript Scope/Closure:爲什麼我可以在這裏訪問內部變量?

var test = (function() { 
    var internal = 5; 
    return { 
     init: function() { 
      $(document).on('click', function() { 
       alert(internal); 
      }); 
     } 
    }; 
}()); 
test.init(); 

我以爲關閉和JavaScript的範圍(我的理解它),意味着一個函數只能訪問自己的變量,並高於1級它。那麼爲什麼這個工作?當我點擊文檔時,我收到「5」的警報,我預計會得到未定義的。

下面是一個的jsfiddle顯示我在做什麼:

http://jsfiddle.net/mcraig_brs/m644L/1/

+0

我相信變量可以在頁面內的任何地方訪問..也就是說,他們的範圍是整個頁面 – Ahmed

+0

查看http://net.tutsplus.com/tutorials/javascript-ajax/closures-front-to-back/有關如何關閉工作的更多細節 –

+1

@AlienArrays:'internal'不是在'test'函數中定義; 'test'結束是指匿名函數返回的對象。 –

回答

4

我想關閉和JavaScript範圍(我的理解它),意味着一個函數只能訪問自己的變量,那1級以上。

不是,它的全部水平以上。事實上,這就是全局變量在JavaScript中的工作方式;他們只是行動中關閉的一個例子。

So爲什麼這樣工作?

當JavaScript引擎需要解決的象徵,它首先(寬鬆),該符號出現在(在這種情況下,通過調用創建你傳遞的匿名函數一個執行上下文到on)。如果在那裏找不到匹配的變量,它會查看圍繞該變量的執行上下文(在本例中,通過調用init創建的變量)。如果它沒有找到它那裏有,它會查看下一個(通過調用最外面的匿名函數創建的)。如果不存在,下一個級別,直到達到全局執行上下文。

更多有關閉(在我的博客):Closures are not complicated

注意,我不停地說「......由調用創建 ......」上面。這是一個關鍵點:在程序運行時,可以(幾乎總是)爲給定範圍創建多個執行上下文。試想一下:

function foo(name) { 
    return function() { 
     alert(name); 
    }; 
} 

(這又是隻有兩個級別,但它適用於儘可能多的水平,只要你喜歡。)

foo,調用時,創建並返回一個函數,調用它時,我們展示該函數創建時被傳遞到foo名稱:

var f1 = foo("one"); 
var f2 = foo("two"); 
f1(); // "one" 
f2(); // "two" 

調用foo創建一個執行上下文。函數foo創建了一個持久的引用,該引用包含該調用的變量(規範將其稱爲「變量綁定對象」)。在foo返回後,該綁定對象仍然存在,這就是爲什麼當我們調用函數foo創建時,它仍然可以訪問相關的name變量。

重要的是要記住,並非閉包獲得變量的的副本。他們得到一個持久參考該變量。這就是爲什麼這個工作原理:

function foo(a) { 
    return function() { 
     alert(++a); 
    }; 
} 
var f = foo(0); 
f(); // 1 
f(); // 2 
f(); // 3 
0

Javascript是一個靜態作用域。當你正在編寫一個函數時,你可以訪問函數中可用的所有變量,因爲它們可以從你訪問的地方得到。

var a = 10; 
function foo() { 
    // now i have access in a 
    var b = 20; 
    // i have access to both a and b 
    function bar() { 
     // still have access to both a and b 
     var c = 30; 
     // any more nested function will have access to a,b and c 
    } 
} 
相關問題