1. 程式人生 > 其它 >淺談JavaScript閉包

淺談JavaScript閉包

什麼是JS閉包?

閉包是指有權訪問另一個函式作用域中變數的函式,建立閉包的最常見的方式就是在一個函式內建立另一個函式,建立的函式可以訪問到當前函式的區域性變數。

閉包的用途

閉包有兩個常用的用途:

  1.使我們在函式外部能夠訪問到函式內部的變數。

  2.使已經執行結束的函式上下文中的變數物件繼續留在記憶體中,因為閉包函式保留了這個變數物件的引用,所以這個變數物件不會被回收。

閉包的應用

閉包可以建構函式的私有屬性、對函式進行節流、防抖操作。但是如果我們濫用閉包,函式中的變數都被儲存在記憶體中,記憶體消耗很大,造成網頁的效能問題,且容易造成記憶體洩漏。解決方法是在退出函式之前,將不使用的區域性變數全部刪除。

程式碼理解

  • 定義假設我們定義函式 A 返回了一個函式 B,並且函式 B 中使用了函式 A 的變數,函式 B 就被稱為閉包。
function A() {
  let a = 1
  function B() {
      console.log(a)
  }
  return B
}
  • 舉例:解決迴圈中使用閉包解決 var 定義函式的問題
for ( var i=1; i<=5; i++) {
    setTimeout( function timer() {
        console.log( i );
    }, i*1000 );
}
  • 首先我們知道setTimeout
    是個非同步函式,所有會先把迴圈全部執行完畢,那麼這時候i就是6了,所以結果會輸出一堆6
  • 如何解決?有三種辦法:
  • 1.使用閉包
for (var i = 1; i <= 5; i++) {
  (function(j) {
    setTimeout(function timer() {
      console.log(j);
    }, j * 1000);
  })(i);
}
  • 2.使用setTimeout的第三個引數
for ( var i=1; i<=5; i++) {
    setTimeout( function timer(j) {
        console.log( j );
    }, i
*1000, i); }
  • 3.使用let定義

  varlet的主要區別在於:let作用域是塊級的,而不是函式級別的。這就意味著使用let關鍵字建立的變數在建立它的“塊”內以及任何巢狀塊中都可用。說的“塊”指的是在for迴圈或if語句中用花括號{}包圍的任何東西。

{ // 形成塊級作用域
  let i = 0
  {
    let ii = i
    setTimeout( function timer() {
        console.log( i );
    }, i*1000 );
  }
  i++
  {
    let ii = i
  }
  i++
  {
    let ii = i
  }
  ...
}