一文了解JavaScript閉包函數(shù)
變量作用域
要理解JavaScript閉包,就要先理解JavaScript的變量作用域。
變量的作用域有兩種:全局的和局部的(全局變量和局部變量)
JavaScript中,在函數(shù)內(nèi)部可以直接讀取到全局變量。
var n=10 function fn(){ alert(n) } fn() //10
而在函數(shù)外部無法讀取到函數(shù)內(nèi)部的變量。
function fn(){ var n=10; } fn() alert(n) //n is not defined 函數(shù)外部無法讀取到函數(shù)內(nèi)部的n
注意:函數(shù)內(nèi)部使用var聲明變量的時候,這個變量是局部變量,如果不使用var,那么這個變量就是一個全局變量。
例如:
function fn(){ n=10; } fn() alert(n) //10
另外,函數(shù)的參數(shù)也是局部性的,只在函數(shù)內(nèi)部起作用。
在正常情況下,我們是無法得到函數(shù)內(nèi)部的局部變量的,只有變通方法才可以——在函數(shù)內(nèi)部再聲明一個函數(shù)。
function f1(){ var n=10; function f2(){ alert(n) } }
f2函數(shù)可以得到f1函數(shù)內(nèi)的所有局部變量,但是f1函數(shù)卻無法得到f2函數(shù)內(nèi)部的局部變量——JavaScript語言特有的“鏈?zhǔn)阶饔糜颉苯Y(jié)構(gòu)。(即子對象會一級一級地向上尋找所有父對象的變量),所以,父對象的所有變量,對于子對象都是可見的。
f2函數(shù)可以獲取到父級函數(shù)f1的局部變量,那么如果把f2()函數(shù)返回,在函數(shù)f1外部就可以訪問到f1()函數(shù)內(nèi)部的變量了。
例如:
function f1(){ var n=10; function f2(){ alert(n) } return f2() } f1() //頁面彈出10
例子中的f2()函數(shù)就是一個閉包函數(shù)。
閉包的概念
由于作用域原因,我們無法在函數(shù)外訪問函數(shù)里面定義的變量,但有事我們又有這個需求,因此就出現(xiàn)了閉包的概念。
閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù)。
在上面的例子中,內(nèi)部函數(shù)f2就是一個閉包函數(shù)。
在本質(zhì)上,閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來的橋梁。
閉包是一種保護(hù)私有變量的機(jī)制,在函數(shù)執(zhí)行時形成私有的作用域,保護(hù)里面的私有變量不受外界干擾。
閉包的用途
(1)可以讀取父級作用域函數(shù)內(nèi)部的變量;
(2)讓變量的值始終保存在內(nèi)存中(讓局部變量變成全局變量),不被垃圾回收機(jī)制清除。
閉包的缺點(diǎn)
由于閉包會使函數(shù)中的變量都保存到內(nèi)存中,垃圾回收機(jī)制不清理,內(nèi)存消耗很大,所以不能濫用閉包,否則可能導(dǎo)致內(nèi)存泄漏。
補(bǔ)充:
什么是內(nèi)存泄漏?
程序的運(yùn)行都是需要內(nèi)存的。只要對內(nèi)存提出要求,操作系統(tǒng)必須供給內(nèi)存。
當(dāng)應(yīng)用程序中的一些代碼變量不再需要用到內(nèi)存時,但是沒有被操作系統(tǒng)或者可用內(nèi)存池回收,就說明它發(fā)生了內(nèi)存泄漏。
即,當(dāng)已經(jīng)不再需要某塊內(nèi)存時,這塊內(nèi)存還存在著——內(nèi)存泄漏
解決閉包引起的內(nèi)存泄漏的問題:
在退出函數(shù)之前,將不使用的局部變量全部刪除。
例如:將當(dāng)前變量的值設(shè)置為‘null',當(dāng)垃圾回收機(jī)制啟動時,會自動對這些值為‘null'的變量回收。
最后總結(jié)一下閉包的好處與壞處
好處
①保護(hù)函數(shù)內(nèi)的變量安全 ,實(shí)現(xiàn)封裝,防止變量流入其他環(huán)境發(fā)生命名沖突
②在內(nèi)存中維持一個變量,可以做緩存(但使用多了同時也是一項(xiàng)缺點(diǎn),消耗內(nèi)存)
③匿名自執(zhí)行函數(shù)可以減少內(nèi)存消耗
壞處
①其中一點(diǎn)上面已經(jīng)有體現(xiàn)了,就是被引用的私有變量不能被銷毀,增大了內(nèi)存消耗,造成內(nèi)存泄漏,解決方法是可以在使用完變量后手動為它賦值為null;
②其次由于閉包涉及跨域訪問,所以會導(dǎo)致性能損失,我們可以通過把跨作用域變量存儲在局部變量中,然后直接訪問局部變量,來減輕對執(zhí)行速度的影響
總結(jié)
到此這篇關(guān)于JavaScript閉包函數(shù)的文章就介紹到這了,更多相關(guān)JavaScript閉包函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實(shí)現(xiàn)的簡單煙花特效代碼
這篇文章主要介紹了JavaScript實(shí)現(xiàn)的簡單煙花特效代碼,涉及JavaScript數(shù)學(xué)運(yùn)算及頁面元素基于定時函數(shù)運(yùn)動的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10JavaScript Base64 作為文件上傳的實(shí)例代碼解析
這篇文章主要介紹了JavaScript Base64 作為文件上傳的實(shí)例代碼解析,非常不錯,具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02通過onmouseover選項(xiàng)卡實(shí)現(xiàn)img圖片的變化
這篇文章主要介紹了通過onmouseover選項(xiàng)卡實(shí)現(xiàn)img圖片的變化,需要的朋友可以參考下2014-02-02javascript中的event loop事件循環(huán)詳解
這篇文章主要給大家介紹了關(guān)于javascript中event loop事件循環(huán)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12IE DOM實(shí)現(xiàn)存在的部分問題及解決方法
IE DOM實(shí)現(xiàn)存在的部分問題及解決方法2009-07-07JavaScript詳解類數(shù)組與可迭代對象的實(shí)現(xiàn)原理
這篇文章主要介紹了JavaScript詳解類數(shù)組與可迭代對象的實(shí)現(xiàn)原理,ES6中引入了迭代器與可迭代對象的概念,并且提供了對可迭代對象的相關(guān)支持,如for...of循環(huán),Map(iterable)構(gòu)造器,展開語法...等。讓我們對數(shù)組外的數(shù)據(jù)集合的遍歷操作也得到極大簡化2022-06-06