當(dāng)前位置:首頁(yè) > IT技術(shù) > Web編程 > 正文

三分鐘理解JS閉包
2022-04-29 13:52:33

先一句話概括:
一個(gè)函數(shù)內(nèi)(父)放另外一個(gè)函數(shù)(子),(子)函數(shù)拿到(父)函數(shù)的局部變量,(父)函數(shù)把(子)函數(shù)返回出去,此時(shí)(子)函數(shù)保留著(父)函數(shù)的私有變量,也就是占據(jù)著空間。這樣,其他函數(shù)(隔壁老王)調(diào)用這個(gè)(子)函數(shù)的時(shí)候,其他函數(shù)(隔壁老王)就可以拿到那個(gè)(父)函數(shù)的局部變量了,調(diào)用一次拿到一次,不管那個(gè)(父)函數(shù)執(zhí)行完畢沒有。

function fn() {
  var i = 1
  return function () {
    console.log(i++)
  }
}

var f = fn()
f() //1
f() //2
f() //3

理解:
看上面的代碼,在函數(shù) a() 里面放一個(gè)函數(shù) inc() ,inc() 拿到 a() 的局部變量 n 。
然后呢, a() 又把 inc 返回出去。?
這樣,c = a() ,就相當(dāng)于 c = inc() [注意:這時(shí)候 inc() 是拿到 a() 里面的 n 并且會(huì)保留著這個(gè) n ,這個(gè) n 不會(huì)隨著 a() 銷毀而銷毀,也就是不會(huì)被垃圾回收機(jī)制回收]。
這樣,c = a() 就相當(dāng)于 c = inc() ,所以最后兩句代碼,是調(diào)用了兩次 c() ,第一次調(diào)用 n++ = 1 , 第二次調(diào)用 n++ = 2 。

總結(jié):
由于在JS中,變量的作用域?qū)儆诤瘮?shù)作用域,在函數(shù)執(zhí)行后作用域就會(huì)被清理、內(nèi)存也隨之被收回,但是由于閉包是建立在一個(gè)函數(shù)內(nèi)部的子函數(shù),由于其可訪問上級(jí)作用域的原因,即使上級(jí)函數(shù)執(zhí)行完,作用域也不會(huì)隨之銷毀,這時(shí)的子函數(shù)—也就是閉包,便擁有了訪問上級(jí)作用域中的變量的權(quán)限,即使上級(jí)函數(shù)執(zhí)行完后,作用域內(nèi)的值也不會(huì)被銷毀。

閉包兩大用處:

1) 一個(gè)是可以讀取函數(shù)內(nèi)部的變量;
2) 另一個(gè)就是讓這些變量的值始終保存在內(nèi)存中。

閉包的常見場(chǎng)景:
一般回調(diào)函數(shù)都有閉包的身影,一個(gè) Ajax 請(qǐng)求的成功回調(diào),一個(gè)事件綁定的回調(diào)方法,一個(gè) setTimeout 的延時(shí)回調(diào),或者一個(gè)函數(shù)內(nèi)部返回另一個(gè)匿名函數(shù),這些都是閉包。簡(jiǎn)而言之,無(wú)論使用何種方式對(duì)某個(gè)函數(shù)內(nèi)部局部變量進(jìn)行傳遞,當(dāng)閉包函數(shù)(子函數(shù))在別處被調(diào)用時(shí),都有閉包的身影。

閉包注意的問題:
由于閉包會(huì)使得函數(shù)中的變量都保存在內(nèi)存中,內(nèi)存消耗很大,所以不能濫用閉包,否則會(huì)造成網(wǎng)頁(yè)的性能問題,在IE中可能導(dǎo)致內(nèi)存泄漏。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。

內(nèi)存泄露:
程序的運(yùn)行需要內(nèi)存。對(duì)于持續(xù)運(yùn)行的服務(wù)進(jìn)程,必須及時(shí)釋放不再用到的內(nèi)存,否則占用越來越高,輕則影響系統(tǒng)性能,重則導(dǎo)致進(jìn)程崩潰。不再用到的內(nèi)存,沒有及時(shí)釋放,就叫做內(nèi)存泄漏。

?

本文摘自 :https://www.cnblogs.com/

開通會(huì)員,享受整站包年服務(wù)立即開通 >