當前位置:首頁 > IT技術 > Web編程 > 正文

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

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

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

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

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

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

閉包兩大用處:

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

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

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

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

?

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

開通會員,享受整站包年服務立即開通 >