js閉包

來源:互聯網
上載者:User

標籤:運行   賦值   handler   理解   方法   str   建議   事件處理   書籍   

  前兩天去面試,被面試官問到平常寫關於什麼方面的閉包知識,頓時有點懵逼,雖然知道閉包是個大概什麼概念,但是在平常的工作中,貌似用的真的比較少,這幾天通過翻閱書籍,就想著來寫一篇關於閉包的文章,瞭解得比較淺,希望看到的大神可以多多指點。

1.什麼是閉包

  閉包也就是指可以訪問其他函數範圍中變數的函數,通常建立閉包的方式就是在一個函數內建立一個函數。

2.閉包的特性

  閉包主要有以下三個特性:

    1.函數嵌套函數

    2.函數內部可以訪問內部的參數和變數

    3.被訪問的參數和變數不會被記憶體回收機制回收。

3.變數範圍

  想要更好地理解閉包,就不得不理解js範圍和範圍鏈的概念。

  js中的變數不外乎兩個:全域變數和局部變數;

  js語言的特點就是函數內部可以訪問全域中定義的變數,但是函數外部卻不能訪問函數內部定義的局部變數

  例1:var global = ‘global’; //定義一個全域變數   

    function test1(){
      console.log(global);                  
    };                                   

    test(); //輸出 global 

  例2: 

    

 註:js沒有塊級範圍的概念,只有函數範圍

4.如何從外部讀取內部變數?

  由於js語言範圍的特點,一般情況下,我們是沒有辦法擷取局部變數的值。但是在實際的應用中,我們有時候需要訪問內部變數,這個時候閉包就派上用場了。

  例:

  

  這樣我們就可以訪問到函數內部定義的局部變數 ,函數test3返回的匿名函數就是一個閉包。

5.使用閉包的好處

  那麼使用閉包到底有什麼好處呢,閉包的好處有以下幾點:

    1.使一個變數長期駐紮在記憶體中

    2.避免全域變數的汙染

    3.私人成員的存在

  一.變數長期駐紮在記憶體中

    例:

      

      解析:以上代碼的解析結果,可以看出,局部變數a在函數test4()執行完畢後,並沒有直接被銷毀,而是一直駐紮在記憶體中。

   二.模組化代碼,減少全域變數的汙染

     例:

      

     解析:將匿名函數的傳回值直接賦值給test5變數,然後執行這個變數。

   三.私人成員的存在

    諸如Java在內的一些語言,支援把方法聲明為私人的,即只能被同一個類中的其他方法調用,就是不支援這樣的原生機制,但是可以通過閉包的方式進行類比私人方法。

    例:

     

6.在迴圈中使用閉包:一個常見的錯誤

  有時候會遇到在一個li列表中,點擊相應的li元素彈出其相應的index值。

  例:

  

  在瀏覽器中運行,會發現不論點擊哪個li,都只會彈出3,而不是其對應的index值,

  該問題的蛀牙原因是賦值給li的onclick事件的是閉包函數而不是閉包對象,在 onclick 的回調被執行時,迴圈早已經完成。

  運用另外一種方法可以解決這個問題,

  

7.效能考量

  在不是非得使用閉包的情況下,建議不要使用閉包,因為閉包多指令碼效能有影響,同時會消耗大量的效能。

8.記憶體流失

  如果閉包的範圍中儲存著對HTML元素,那就意味著改元素無法被銷毀。

  例:function assignHandler(){
      var element = document.getElementById(‘id‘);
      element.onclick = function(){
        console.log(element.id);
      }
    }

  解析:以上代碼建立了一個作為element元素的事件處理常式的閉包,而在這個閉包內部又對改元素進行了引用。由於匿名函數儲存了對assignHandler()的函數對象的引用,所以對於element變數的引用至少為1,所以該變數會一直存在在記憶體中,不會被回收。可以通過改寫一下:

    function assignHandler(){
      var element = document.getElementById(‘id‘);

      var id = element.id;

      element.onclick = function(){
        console.log(id);
      };

      element = null;
    }

   通過將element.id 的一個副本儲存在一個變數中,並在閉包中使用消除了循環參考,必須要記住:閉包會引用包含函數的整個使用中的物件,而這個使用中的物件中包含element。即使閉包不引用,但是包含函數的使用中的物件也會保持著對其的引用,所以有必要將其設定為null。

    

 

js閉包

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.