閉包

最近正在整理一些JS的基礎知識,看見閉包這個詞,突然覺得有必要記錄一下:
在ES6的塊級作用域出現(xiàn)之前,是沒有塊級作用域的概念的,這就導致當想訪問一個函數內部變量的時候,會出現(xiàn)一定的困難,這個時候閉包就出現(xiàn)了。
我們最初接觸閉包的時候,很大概率是通過以下情況:

function fn(){
 var li = document.getElementsByTagName("li");
 for(var i = 0; i < li.length; i++){
   li[i].onclick = function(){
     console.log(i);
   }
 }
}  
fn(); 

運行的結果是這樣的:每點擊一個li,打印出來的都是 li的長度;為什么會出現(xiàn)這么個結果呢?這就從JS中的作用域鏈講起。
什么是JS的作用域鏈?
簡單來說就是在函數中所能訪問的變量按照層級關系所組成的一條有著先后順序的鏈子。所以每個函數最先能訪問的變量(也就是在這條鏈子上最先能接觸到的)是當前函數的活動對象(就是在函數當中定義或重新賦值的變量),其次下一個能訪問的變量就是當前的函數所在的包含環(huán)境。然后是下下個包含環(huán)境。這樣一層層的找下去,直到找到全局執(zhí)行環(huán)境為止。
所以,以上題目的結果,可以解釋:每個li標簽的onclick事件執(zhí)行時,本身onclick綁定的function的作用域中沒有變量i,i為undefined,則解析引擎會尋找父級作用域,發(fā)現(xiàn)父級作用域中有i,且for循環(huán)綁定事件結束后,i已經賦值為4,所以每個li標簽的onclick事件執(zhí)行時,打印的都是父作用域中的i,也就是4。這是作用域的問題。

所以根據以上解釋,我們只能把i存放在一個變量之中,這時候閉包就出現(xiàn)了:

function fn(){
  var li = document.getElementsByTagName("li");
  for(var i = 0; i < li.length; i++){
    li[i].onclick = function(n){
      return function(){
        console.log(n);
      }
    }(i)
  }
}  
fn();

所以閉包的含義就很明顯了:閉包是指有權訪問另一個函數作用域中的變量的函數。

那么閉包的作用:
1、可以在函數的外部訪問到函數內部的局部變量。
2、讓這些變量始終保存在內存中,不會隨著函數的結束而自動銷毀。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容