看到一篇文章對于閉包的定義挺好的,整理一下
閉包的定義:在函數A內部定義一個函數B,函數B可以訪問函數A中的變量,我們稱函數B為閉包
閉包的意義:我們可以間接的訪問函數內部的變量
在紅寶書中舉例大都是:
圖一
有的同學定義的閉包的定義為:一個函數內部嵌套一個函數,返回一個函數,并能夠訪問該函數的內部變量,但其實不完整,下面的例子反駁了這個觀點:
圖二
循環中也會用閉包解決‘var’定義的問題
圖三
首先因為setTimeout是異步函數,會先將循環執行完成以后,再執行,此時i已經是6(變量i是var定義的,所以全局只有一個i,每一次的循環都會更新,即最后i為6)
關于閉包需要了解js的GC機制:
在js中如果一個對象不被引用就會被GC機制回收,否則這個對象就會一直存在。在前面的例子中,B定義在A中,因此B依賴于A,如果B被外界的變量C引用,就說明A間接的被C引用。也就是說A不會被GC回收。
解決辦法有三種:
第一種采用閉包的方式:
圖四
在上面的代碼中使用了立即執行的函數,將變量i傳入,賦值給j,此時就將值固定在j上,在函數內部執行timer這個函數的時候使用j這個變量,從而達到目的。
第二種:使用setTimeout的第三個參數的方式
圖五
給setTimeout設置參數i,這個參數作為j傳入函數timer
第三種方法:使用用let來定義i,形成塊級作用域,進而解決問題
圖六