看到一篇文章對(duì)于閉包的定義挺好的们童,整理一下
閉包的定義:在函數(shù)A內(nèi)部定義一個(gè)函數(shù)B自脯,函數(shù)B可以訪問函數(shù)A中的變量贞谓,我們稱函數(shù)B為閉包
閉包的意義:我們可以間接的訪問函數(shù)內(nèi)部的變量
在紅寶書中舉例大都是:
有的同學(xué)定義的閉包的定義為:一個(gè)函數(shù)內(nèi)部嵌套一個(gè)函數(shù)十性,返回一個(gè)函數(shù)叛溢,并能夠訪問該函數(shù)的內(nèi)部變量,但其實(shí)不完整劲适,下面的例子反駁了這個(gè)觀點(diǎn):
循環(huán)中也會(huì)用閉包解決‘var’定義的問題
首先因?yàn)閟etTimeout是異步函數(shù)楷掉,會(huì)先將循環(huán)執(zhí)行完成以后,再執(zhí)行霞势,此時(shí)i已經(jīng)是6(變量i是var定義的烹植,所以全局只有一個(gè)i斑鸦,每一次的循環(huán)都會(huì)更新,即最后i為6)
關(guān)于閉包需要了解js的GC機(jī)制:
在js中如果一個(gè)對(duì)象不被引用就會(huì)被GC機(jī)制回收草雕,否則這個(gè)對(duì)象就會(huì)一直存在巷屿。在前面的例子中,B定義在A中墩虹,因此B依賴于A嘱巾,如果B被外界的變量C引用,就說明A間接的被C引用败晴。也就是說A不會(huì)被GC回收浓冒。
解決辦法有三種:
第一種采用閉包的方式:
在上面的代碼中使用了立即執(zhí)行的函數(shù),將變量i傳入尖坤,賦值給j稳懒,此時(shí)就將值固定在j上,在函數(shù)內(nèi)部執(zhí)行timer這個(gè)函數(shù)的時(shí)候使用j這個(gè)變量慢味,從而達(dá)到目的场梆。
第二種:使用setTimeout的第三個(gè)參數(shù)的方式
給setTimeout設(shè)置參數(shù)i,這個(gè)參數(shù)作為j傳入函數(shù)timer
第三種方法:使用用let來定義i纯路,形成塊級(jí)作用域或油,進(jìn)而解決問題