完全弄懂JS中閉包

閉包概念:html

  閉包就是有權訪問另外一個函數做用域中變量的函數.
分析這句話:閉包

  1.閉包是定義在函數中的函數.
  2.閉包能訪問包含函數的變量.
  3.即便包含函數執行完了, 被閉包引用的變量也得不到釋放.函數

例子分析-1:
    
        function add(){
            var i = 0
                arr = [];
            for(; i < 10; i++){
                arr.push(function(){
                    alert(i);
                });
            }
            return arr;
        }
        var temp = add();
        temp[0]();
        
        你們猜猜這個結果是多少? 0, i, 10?
        我想你們會說是0.
        可是結果是10.
        
        我想你們想的應該是這樣滴:
         i = 0, arr.push(function(){
            alert(0);
         })
         i = 1, arr.push(function(){
            alert(1);
         })
        ...
         i = 10, arr.push(function(){
            alert(10);
         })
         
        咋一看, 這個確實合理, 根據閉包的定義, 具體這個固然是上面分析的那樣了.
        問題就出在這個變量的理解上.
        
        1.i是變量不假, 可是i在for循環的時候, 一直在不斷變化. 也就是說這個i在參與for循環的時候, 值是不肯定的, 等到for執行完後, i的值才肯定.
        2.每次push一個匿名函數表達式時, 那只是定義一個函數, 並沒去執行那個函數, 因此那個函數裏引用的外部變量都是原封不動的放進去的.
          換句話說, 就是這個匿名函數在最後執行的時候, 纔會去查找做用域鏈, 直至找到那個變量i爲止.
        
        也就是:
             i = 0, arr.push(function(){
                alert(i);
             })
             i = 1, arr.push(function(){
                alert(i);
             })
             ...
             i = 10, arr.push(function(){
                alert(i);
             })
        
        執行add()時, i參與循環完畢, i = 10. 
        執行temp[0]()時, 匿名函數會查找i, 先看本身, 個人i有值嗎?沒有. 再找他的上級函數, i有值嗎?有, i = 10. 查找結束.
        至此, 無論執行temp[0](), 仍是temp[5](), 仍是temp[10](), 結果都是10.
        
        改一下上面的例子, 讓它符合咱們的預期要求.
        
        例子分析-2:
        
          function add(){
            var i = 0
                arr = [];
            for(; i < 10; i++){
                arr.push(
                (function(n){
                    return function(){
                        alert(n);
                    }
                })(i)//注意這個變化

                );
            }
            return arr;
        }
        var temp = add();
        temp[0]();
        temp[1]();
        ...
        
        此次結果是預期的,結果是 0 , 1 , 2,  3 ... 10
        
        分析一下循環那部分.
        (function(n){
            return function(){
                alert(n);
            }
        })(i)

        這個叫作當即執行的匿名函數表達式(不清楚這種寫法的, 能夠先google下, 或者看個人單獨一篇專門介紹)
        
        i這個是時候就被當作參數傳遞了, 每次這個匿名函數執行時, i都會把本身的值複製一份給n
        return語句中的匿名函數引用着n, 此時已經和i無關了.
        
        每次匿名函數表達式執行時, 都會保存一個不一樣的n.
        return語句中的匿名函數每次也引用着不一樣的n。
        
        形象點就是這樣:
            arr.push(
                (function(n = i = 0){
                    return function(){
                        alert(n = 0);
                    }
                })(i = 0)
            )
            arr.push(
                (function(n = i = 1){
                    return function(){
                        alert(n = 1);
                    }
                })(i = 1)
            )
            ...


  閉包的介紹就到此爲止了.

轉自http://www.cnblogs.com/tinkbe...google

相關文章
相關標籤/搜索