2012-07-05

Javascript closure

Javascript closure 對 Java programmer 來說是個陌生又奇怪的概念。

原本以為 closure 就是 callback function,可以將 function 當參數傳給別個 function,稍後可以執行,今天發現一個邏輯上的問題,才搞清楚什麼是 closure。

當宣告 function 時,可以在 function 參照(也就是使用)當下 scope 看得到的所有變數,重點來了,但是當 function 被當作 callback 傳出去時,function裡用到的變數就會是問題,如果是 global 變數當然沒問題,任何地方都可以看得到 global 變數,但是 local 變數呢?出了這個村就看不到 local 變數啦!


腦袋又要冒煙了!
var globalIdx = 30; // global 變數
var thatIdx = 90; // global 變數
var that = this; // 從其他地方使用 that 參照這個 this,也就是 window

$(function(){

    var localIdx = 0; // 主角,local 變數
    this.thisIdx = 60; // 奇怪的角色,物件屬性,ready function 屬於 document,所以 thisIdx 就是 document 的屬性
    var ready = this; // 從其他地方參照這個 this,也就是 document
   
    window.setInterval(function(){
        neil.log('from ' + this); // 驗明正身,看看 setInterval 的 callback 是在哪個 context 裡執行,結果無誤,還是 window
        neil.log('localIdx: ' + localIdx++); // 讀取 local 變數
        neil.log('globalIdx: ' + globalIdx++); // 曖昧讀取 global 變數
        neil.log('that.globalIdx: ' + that.globalIdx++); // 指名道姓讀取
        neil.log('this.thisIdx: ' + this.thisIdx++); // 曖昧讀取
        neil.log('ready.thisIdx: ' + ready.thisIdx++); // 指名道姓讀取
        neil.log('that.thatIdx: ' + that.thatIdx++); // 指名道姓讀取
        neil.log('-');
    }, 3000);
});
結果如下:
from [object Window]
localIdx: 0
globalIdx: 30
that.globalIdx: 31
this.thisIdx: NaN
ready.thisIdx: 60
that.thatIdx: 90
-
from [object Window]
localIdx: 1
globalIdx: 32
that.globalIdx: 33
this.thisIdx: NaN
ready.thisIdx: 61
that.thatIdx: 91
-
from [object Window]
localIdx: 2
globalIdx: 34
that.globalIdx: 35
this.thisIdx: NaN
ready.thisIdx: 62
that.thatIdx: 92
-
window.setInterval() 的執行是在 ready function 結束之後,按照常理,出了 ready function,function 裡的 local 變數應該就再也見不到了,所以 localIdx 與 ready 這兩個 local 變數應該在 setInterval() 裡的 callback 看不到才對,但是卻正確的執行了。

這就是 closure。

closure 就是 function 加上用到的 local 變數 。

沒有留言:

張貼留言