JavaScript-閉包

閉包(Closure)概念

在A函數(shù)中定義了一個B函數(shù)亭畜,在B函數(shù)中使用了A函數(shù)中的變量倦沧,就會產(chǎn)生閉包,其中B就是一個閉包墩弯。
也可以說省骂,定義在一個函數(shù)內(nèi)部的這個函數(shù)就是閉包。

理解閉包需要的幾個相關概念

1.變量的作用域

在ES5中變量有兩個作用域:

  1. 全局作用域(global)
  2. 局部作用域(local)

在ES6中補充了一個新的作用域-塊級作用域(block)

當定義變量的地方?jīng)]有被 function 包括則是全局變量最住,否則就是局部變量钞澳。

在函數(shù)的內(nèi)部會優(yōu)先使用局部變量(即使全局變量和局部變量同名亦是如此),在函數(shù)調(diào)用的過程涨缚,會給局部變量創(chuàng)建一個函數(shù)棧區(qū)(區(qū)別于全局棧)策治,來保存這些局部變量。正常情況下在函數(shù)調(diào)用結束后兰吟,函數(shù)棧會被垃圾回收機制處理通惫。

2.執(zhí)行上下文

  • 代碼的運行會產(chǎn)生執(zhí)行上下文,如果代碼不運行就沒有。
  • 全局代碼產(chǎn)生全局上下文
  • 函數(shù)代碼產(chǎn)生函數(shù)上下文
  • 函數(shù)嵌套調(diào)用形成執(zhí)行上下文棧
  • 執(zhí)行上下文中保存了執(zhí)行代碼所需要的各類的數(shù)據(jù)
  • 執(zhí)行上下文是一個對象,在代碼運行過程中產(chǎn)生,代碼運行完成后就消失.

執(zhí)行上下文的組成

  1. 自己的執(zhí)行上下文
  2. 父級函數(shù)的執(zhí)行上下文

全局上下文

一旦<script></script>標簽中代碼運行起來,就會產(chǎn)生一個執(zhí)行上下文,這個執(zhí)行上下文就是全局執(zhí)行上下文.

  • 全局上下文只有一個
  • 全局執(zhí)行環(huán)境是window對象,所有變量和函數(shù)都作為window對象的屬性和方法創(chuàng)建的
  • 所有的代碼都在全局執(zhí)行上下文中執(zhí)行

函數(shù)執(zhí)行上下文

每次調(diào)用函數(shù)都會產(chǎn)生一個執(zhí)行上下文混蔼,函數(shù)調(diào)用完成后履腋,會把執(zhí)行上下文釋放掉。
按照函數(shù)的調(diào)用順序惭嚣,這些上下文以棧的形式存儲(先進后出).棧底是全局上下文遵湖。

3.詞法作用域-靜態(tài)作用域

js代碼的書寫順序,就決定了變量的作用域晚吞。換言之延旧,在函數(shù)內(nèi)部去訪問一個變量,應該去定義這個函數(shù)(寫這個函數(shù)的位置)的相關作用域中去找槽地,而不是調(diào)用這個函數(shù)的那個作用域中去找迁沫。

舉個栗子就比較好懂些,如下圖

4.函數(shù)的嵌套定義

在JS中,在函數(shù)體中可以再次定義另一個函數(shù);并且可以多層函數(shù)嵌套使用捌蚊。

5.作用域鏈

在JS中有兩條鏈集畅,分別是作用域鏈和原型鏈,這里要著重說到作用域鏈缅糟。
在函數(shù)的內(nèi)部牡整,要確定一個變量的值,會從當前的作用域出發(fā)溺拱,沿著作用域鏈向上找逃贝,如果找到全局作用域中還是沒有找到,那么就會報引用類型錯誤迫摔。

再次理解閉包

從閉包的定義可以抓住兩個關鍵點:

  • 函數(shù)嵌套定義
  • 引用變量

通過前面的幾個相關知識點沐扳,可以發(fā)現(xiàn)在JS中,函數(shù)內(nèi)部可以通過作用域鏈機制輕松得到父級函數(shù)內(nèi)的變量乃至全局變量句占,而反過來則是行不通的沪摄,即函數(shù)外部是無法讀取函數(shù)內(nèi)局部變量的。

那么如果有的場景必須要得到函數(shù)內(nèi)部的局部變量時纱烘,需要變通方法那么就產(chǎn)生了閉包杨拐。

可以在本質(zhì)上去理解閉包,閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來的一座橋梁擂啥,可以使局部變量被外部函數(shù)訪問到哄陶,也就是說變相的延長了函數(shù)中局部變量的壽命。

上段代碼

function f(){  
    var a = 1;
    function f1(){
        console.log(a);
    }
    return f1;
} 
var r = f();
r();

這段代碼執(zhí)行后,結果輸出為1哺壶。也就是說當函數(shù)f調(diào)用結束后屋吨,它的局部變量a并沒有被回收掉蜒谤。可以說這就是閉包的本質(zhì)至扰,它使得函數(shù)調(diào)用結束后鳍徽,被閉包引用的變量沒有被回收機制干掉而順利存活了下來,還可以被外部訪問和使用敢课。

閉包的作用

根據(jù)前面的理解,可以歸納閉包的作用有:

  1. 讀取函數(shù)內(nèi)部的變量
  2. 延長這些變量的生命周期

使用閉包的栗子來一個 - 節(jié)流函數(shù)

節(jié)流函數(shù)阶祭,可以讓一個函數(shù)變得"懶",調(diào)用一次之后需要隔一段時間才能再次調(diào)用直秆,即降低函數(shù)的可被調(diào)用的頻率濒募。話不多說上代碼

上面的代碼中,f1就是被節(jié)流函數(shù)變懶了的test切厘。
代碼運行中萨咳,f函數(shù)中t1這個局部變量被f函數(shù)內(nèi)部定義的t函數(shù)引用后懊缺,當f函數(shù)調(diào)用執(zhí)行完畢后疫稿,t1這個變量并沒有隨之被回收,而是一直可以被訪問鹃两。這就是閉包的體現(xiàn)遗座。

閉包的弊端

  1. 閉包會使函數(shù)內(nèi)的變量一直被保存在內(nèi)存中, 這是極耗內(nèi)存的方式。不可以濫用閉包俊扳,會對網(wǎng)頁的性能有很大的影響途蒋。在IE中可能會導致內(nèi)存泄露。
  2. 閉包在函數(shù)外部可以訪問并改變函數(shù)內(nèi)部變量的值馋记,這是好事也是壞事号坡。 如果把父級函數(shù)作為對象使用,而把閉包作為它的公用方法梯醒,而又把其內(nèi)部變量作為它的私有屬性宽堆,這時就一定要注意了,不要輕易改變父級函數(shù)內(nèi)部變量的值茸习。

以上就是對JavaScript中閉包的復習??

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末畜隶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子号胚,更是在濱河造成了極大的恐慌籽慢,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件猫胁,死亡現(xiàn)場離奇詭異箱亿,居然都是意外死亡,警方通過查閱死者的電腦和手機弃秆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門极景,熙熙樓的掌柜王于貴愁眉苦臉地迎上來察净,“玉大人,你說我怎么就攤上這事盼樟∏饪ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵晨缴,是天一觀的道長译秦。 經(jīng)常有香客問我,道長击碗,這世上最難降的妖魔是什么筑悴? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮稍途,結果婚禮上阁吝,老公的妹妹穿的比我還像新娘。我一直安慰自己械拍,他們只是感情好突勇,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著坷虑,像睡著了一般甲馋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上迄损,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天定躏,我揣著相機與錄音,去河邊找鬼芹敌。 笑死痊远,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的氏捞。 我是一名探鬼主播碧聪,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼幌衣!你這毒婦竟也來了矾削?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤豁护,失蹤者是張志新(化名)和其女友劉穎哼凯,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體楚里,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡断部,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了班缎。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝴光。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡她渴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蔑祟,到底是詐尸還是另有隱情趁耗,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布疆虚,位于F島的核電站苛败,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏径簿。R本人自食惡果不足惜罢屈,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望篇亭。 院中可真熱鬧缠捌,春花似錦、人聲如沸译蒂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蹂随。三九已至十嘿,卻和暖如春因惭,著一層夾襖步出監(jiān)牢的瞬間岳锁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工蹦魔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留激率,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓勿决,卻偏偏與公主長得像乒躺,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子低缩,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 閉包(closure)是Javascript語言的一個難點嘉冒,也是它的特色,很多高級應用都要依靠閉包實現(xiàn)咆繁。 一讳推、變量...
    zouCode閱讀 1,270評論 0 13
  • javascript之閉包 閉包的概念 ????閉包(closure)是 JavaScript 的一種語法特性。 ...
    呦_小宋啊閱讀 207評論 0 2
  • 目錄 1.執(zhí)行環(huán)境與作用域鏈 2. 立即執(zhí)行函數(shù) 3. 閉包知識點 3.1 什么是閉包 3.2 使用閉包的意義與注...
    犯迷糊的小羊閱讀 629評論 0 11
  • 前言 這篇文章使用有效的javascript代碼向程序員們解釋了閉包玩般,大牛和功能型程序員請自行忽略银觅。 基礎篇 閉包...
    kiaizi閱讀 355評論 0 7
  • 前言 總括 :這篇文章使用有效的javascript代碼向程序員們解釋了閉包,大牛和功能型程序員請自行忽略坏为。 譯者...
    KX九五閱讀 275評論 0 1