JS - 閉包
阿新 • • 發佈:2020-10-20
可能大多數人平時大量寫js程式碼,但是對閉包還是模模糊糊。本文記錄自己學習閉包的一些知識點。
function foo() { var a = 2; function bar() { console.log(a) }; return bar; } var result = foo() // result就是foo返回的bar result() // 呼叫了bar,成功訪問了函式作用域中的變數a
以上就是一個閉包的程式碼。foo()執行後,foo()內部作用域會被銷燬,JS垃圾回收器回收無用的空間,釋放記憶體。但是由於閉包的存在,會使它一直存在。因為bar()本身在使用這個作用域。bar()對foo()作用域的引用就叫閉包。
傳遞函式的方式觀察閉包,通過內部函式baz傳遞過來,由於baz涵蓋了foo作用域,所以能夠訪問到a
function foo() { var a; function bar() { console.log(a) } baz(bar) } function baz(fn) { fn() //這就是閉包 }
在平時編碼過程中,閉包隨處可見。比如將函式作為引數到處傳,那麼就會在這些函式呼叫中找到閉包。比如平時常見的定時器。
for(var i=0; i<=5; i++) { setTimeout(function timer() { console.log(i) }, i*1000) }
以上程式碼,我們期望它能每一秒依次輸出1-5,但是其實它的結果是 6 個 6,這是由於 i 其實是一個全域性作用域,並沒有在每次迴圈中儲存。for迴圈到最後i的結果是6。
我們可以通過閉包來解決這種問題,將每次迴圈的i值傳入閉包函式中進行儲存。
for(var i=0; i<=5; i++) { (function(j){ setTimeout(function timer() { console.log(j) }, j*1000) })(i) }
es6中新增了let,也可以解決以上問題,更加簡便。
for(let i=0; i<=5; i++) { setTimeout(function timer() { console.log(i) }, i*1000) }