每次看到j(luò)Query的時候,首先想到的就是閉包。這是個常談的問題了。今天重新回憶了一下閉包。
什么是閉包? 當(dāng)有一個函數(shù)想要訪問另一個函數(shù)內(nèi)部的變量,這個是訪問不了的。所有我們要用閉包來訪問。所以簡單的來說,閉包就是連接函數(shù)內(nèi)部和外部的一座橋梁,通過閉包我們能夠訪問其他函數(shù)內(nèi)部的變量。
想了解閉包,首先要知道作用域。最簡單來說:全局變量和局部變量。
全局變量(Global variable):可以在腳本的任何位置被引用。
局部變量(Local variable):只存在于聲明它的那個函數(shù)的內(nèi)部,這個函數(shù)之外是無法引用的。
使用var聲明的變量在當(dāng)前作用域里面才起作用,未使用var申明的變量,不管在任何地方聲明的,都是全局變量。用var聲明的變量不一定是局部變量
閉包最大的作用就是全局變量私有化。在上面講過閉包能夠訪問其他函數(shù)內(nèi)部的變量,還有一個就是能后永久的把一個變量保存在當(dāng)前作用域中。不會隨著函數(shù)調(diào)用完之后會被JavaScript特有的垃圾回收機制回收。
本文我們以閉包兩種的主要形式來學(xué)習(xí)。
在這段代碼中,a()中的返回值是一個匿名函數(shù),這個函數(shù)在a()作用域內(nèi)部,所以它可以獲取a()作用域下變量name的值,將這個值作為返回值賦給全局作用域下的變量b,實現(xiàn)了在全局變量下獲取到局部變量中的變量的值。
一般情況下,在函數(shù)fn執(zhí)行完后,就應(yīng)該連同它里面的變量一同被銷毀,但是在這個例子中,匿名函數(shù)作為fn的返回值被賦值給了fn1,這時候相當(dāng)于fn1=function(){var n = 0 ... },并且匿名函數(shù)內(nèi)部引用著fn里的變量num,所以變量num無法被銷毀,而變量n是每次被調(diào)用時新創(chuàng)建的,所以每次fn1執(zhí)行完后它就把屬于自己的變量連同自己一起銷毀,于是乎最后就剩下孤零零的num,于是這里就產(chǎn)生了內(nèi)存消耗的問題。
保護函數(shù)內(nèi)的變量安全 ,實現(xiàn)封裝,防止變量流入其他環(huán)境發(fā)生命名沖突;
在內(nèi)存中維持一個變量,可以做緩存(但使用多了同時也是一項缺點,消耗內(nèi)存);
匿名自執(zhí)行函數(shù)可以減少內(nèi)存消耗。
其中一點上面已經(jīng)有體現(xiàn)了,就是被引用的私有變量不能被銷毀,增大了內(nèi)存消耗,造成內(nèi)存泄漏,解決方法是可以在使用完變量后手動為它賦值為null;
其次由于閉包涉及跨域訪問,所以會導(dǎo)致性能損失,我們可以通過把跨作用域變量存儲在局部變量中,然后直接訪問局部變量,來減輕對執(zhí)行速度的影響。
學(xué)習(xí)完整體系全新Java入門架構(gòu)師、全棧開發(fā)課程請私信我或者看圖片聯(lián)系。
聯(lián)系客服