淺談JavaScript閉包
阿新 • • 發佈:2021-08-12
什麼是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定義
var
和let
的主要區別在於: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 } ... }