1. 程式人生 > >js基礎知識(5)-閉包

js基礎知識(5)-閉包

閉包的定義很簡單:函式 A 返回了一個函式 B,並且函式 B 中使用了函式 A 的變數,函式 B 就被稱為閉包。

function A() {
let a = 1
function B() {
console.log(a)
}
return B
}


你是否會疑惑,為什麼函式 A 已經彈出呼叫棧了,為什麼函式 B 還能引用到函式A 中的變數。因為函式 A 中的變數這時候是儲存在堆上的。現在的 JS 引擎可以通過逃逸分析辨別出哪些變數需要儲存在堆上,哪些需要儲存在棧上

經典面試題,迴圈中使用閉包解決 var 定義函式的問題

for ( var i=1; i<=5; i++) {
setTimeout( function timer() {
console.log( i );
}, i*1000 );
}

首先因為 setTimeout 是個非同步函式,所有會先把迴圈全部執行完畢,這時候 i就是 6 了,所以會輸出一堆 6。

解決辦法一:使用閉包

for (var i = 1; i <= 5; i++) {
(function(j) {
setTimeout(function timer() {
console.log(j);
}, j * 1000);
})(i);
}

第二種就是使用 setTimeout 的第三個引數

for ( var i=1; i<=5; i++) {
setTimeout( function timer(j) {
console.log( j );
}, i*1000, i);
}

第三種就是使用 let 定義 i 了
 

for ( let i=1; i<=5; i++) {
setTimeout( function timer() {
console.log( i );
}, i*1000 );
}

因為對於 let 來說,他會建立一個塊級作用域,相當於
 

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