針對前端必會的閉包,梳理一番,媽媽不再用擔憂個人閉包了~~~~

閉包

1.1 什麼是閉包

  • 閉包(closure): 指有權訪問另外一個函數做用域中變量的函數。
  • 通俗講:一個做用域能夠訪問另一個函數內部的局部變量。

1.2 觀察下面代碼的結果

for(var i = 0; i < 10; i++) {  
    setTimeout(function() {  
        console.log(i);
    }, 1000);  
}
//輸出結果都爲10,由於for()循環過程當中每次傳值,匿名函數並無執行,至關於執行10次function(){console.log(i);},循環結束i變爲10,因此輸出所有爲10;
複製代碼
for(var i = 0; i < 10; i++) {  
    (function(i) {  
        setTimeout(function() {  
            console.log(i);
        }, 1000);  
    })(i);  
}
//外部匿名函數當即執行,把 i 做爲參數,賦值給內部的 i ,由於是當即執行,因此每次循環輸出不一樣值。
複製代碼

1.3 變量的做用域與同步異步複習

變量根據做用域的不一樣分爲兩種:全局變量和局部變量

  • 函數內部可使用全局變量。
  • 函數外部不可使用局部變量。
  • 當函數執行完畢,本做用域內的局部變量會銷燬。

同步異步

  • 同步:因爲js單線程,同步任務都在主線程上排隊執行,前面任務沒執行完成,後面的任務會一直等待;閉包

  • 異步:不進入主線程,進入任務隊列,等待主線程任務執行完成後開始執行。好比咱們學的異步操做setTimeout和setInterval,等待主線程任務執行完,在開始執行裏面的函數異步

1.3閉包的做用

  • 特性:可實現函數外訪問函數內變量,外層變量能夠不被垃圾回收機制回收,即延伸變量的做用範圍函數

  • 缺點: 引用外層變量不被回收,會相比其餘函數佔用更高內存,使用不當容易形成內存泄漏。ui

1.4 經典案例

利用閉包的方式獲得當前li 的索引號

for (var i = 0; i < lis.length; i++) {
// 利用for循環建立了當即執行函數
// 當即執行函數也成爲小閉包由於當即執行函數裏面的任何一個函數均可以使用它的i這變量
(function(i) {
    lis[i].onclick = function() {
      console.log(i);
    }
 })(i);
}
複製代碼

方法二: 使用自定義屬性,給每一個對象添加一個索引屬性

for (var i = 0; i < lis.length; i++) {
function(i) {
    lis[i].index = i;
    lis[i].onclick = function() {
      console.log(this.index);
    }
 }
}
複製代碼

方法三: 利用ES6 的 Let 聲明變量就能夠更好的解決上述問題

for (let i = 0; i < lis.length; i++) {
function(i) {
    lis[i].onclick = function() {
      console.log(i)
    }
 }
}
複製代碼
相關文章
相關標籤/搜索