閉包詳細圖解

前言

在我們了解了執(zhí)行上下文EC之后荣瑟,我們應(yīng)該知道了扫皱,js執(zhí)行的正常流程足绅。但是我們在工作、面試時經(jīng)常會遇到閉包這個奇怪的東西韩脑,今天我們就來詳細的了解一下氢妈。閉包是如何形成的,閉包在ECS中是如何執(zhí)行的段多。

正文

作用域和作用域鏈

講閉包之前我們需要先了解作用域和作用域鏈首量。

作用域: 表示一個變量的可用范圍,從而避免不同范圍的變量之間相互干擾。

作用域分為兩種:

  • 全局作用域:在瀏覽器端全局作用域就是window加缘,他可以重復(fù)使用鸭叙,隨處可用。但是全局作用的定義的變量容易被污染
  • 函數(shù)作用域:函數(shù)聲明的時候會自動創(chuàng)建函數(shù)作用域?qū)ο髎cope,他指向函數(shù)聲明時的作用域拣宏。而每個函數(shù)調(diào)用時創(chuàng)建的AO對象前會先創(chuàng)建當前函數(shù)的作用域沈贝,并創(chuàng)建parent對象通過函數(shù)聲明時的作用域?qū)ο髎cope指向他函數(shù)的父級作用域。他不會污染全局勋乾,但是不會重復(fù)使用缀程。函數(shù)執(zhí)行完畢后會隨著函數(shù)執(zhí)行上問出棧=>AO對象銷毀而銷毀

作用域鏈

變量取值到創(chuàng)建這個變量的函數(shù)的作用域中取值。但是如果在當前作用域中沒有查到值市俊,就會向通過parent對象去父作用域去查杨凑,直到查到全局作用域,這么一個查找過程形成的鏈條就叫做作用域鏈摆昧。

閉包

為什么會使用閉包撩满?

我們先總結(jié)下全局變量和局部變量的優(yōu)缺點。

  • 全局變量:可以重用绅你、但是會造成全局污染而且容易被篡改
  • 局部變量:僅函數(shù)內(nèi)使用不會造成全局污染也不會被篡改伺帘、不可以重用
    從上面可以看出全局變量和局部變量的優(yōu)缺點剛好是相對的。閉包的出現(xiàn)正好結(jié)合了全局變量和局部變量的優(yōu)點忌锯。

閉包是怎么形成伪嫁,在ECS如何執(zhí)行的呢?

我們以一下代碼為例:

function add(){
  var n = 0
  return function(){
    n++
    console.log(n)
  }
}
const num = add()
num()
num()
num()

代碼開始執(zhí)行時

首先創(chuàng)建全局執(zhí)行上下文偶垮,并將全局執(zhí)行上下文壓入執(zhí)行上下文棧底张咳。

那么全局執(zhí)行上下文活動對象AO=>window對象中會有以下內(nèi)容


image

執(zhí)行順序:

  • 全局函數(shù)add => 內(nèi)存地址 => add(){....}
  • 全局變量num => undefined
    函數(shù)在聲明時會自動創(chuàng)建一個scope對象指向創(chuàng)建時的作用域(AO活動對象),此時作用域是window似舵,所以聲明的add函數(shù)的socpe指向window

add()執(zhí)行

image

執(zhí)行順序:

  • add執(zhí)行上下文入棧脚猾,創(chuàng)建add活動對象AO
    • add函數(shù)AO對象中有:
    • 局部變量n => 0
    • parent => window對象(parent根據(jù)add函數(shù)聲明時scope)
  • add執(zhí)行返回一個函數(shù),函數(shù)聲明創(chuàng)建scope對象指向當前作用域 => add活動對象AO
  • 返回的函數(shù)砚哗,函數(shù)被全局變量num引用

add()執(zhí)行完成龙助,出棧

image.png

add()執(zhí)行完成。add的執(zhí)行上下文出棧蛛芥。

此時問題來了提鸟。

add()執(zhí)行上下文已經(jīng)出棧了。但是add的活動對象AO沒有被釋放仅淑!

為什么呢? 根據(jù)圖片的我標注出來的紅線称勋,這里形成了一個循環(huán)引用。所有add的活動對象AO無法被釋放漓糙。這樣就形成了一個閉包铣缠。

num()執(zhí)行

image

執(zhí)行順序:

  • num執(zhí)行上下文入棧。創(chuàng)建num活動對象AO
    • num函數(shù)AO對象中:
    • parent => add函數(shù)AO對象(parent根據(jù)num函數(shù)聲明時scope)
  • 執(zhí)行n++,發(fā)現(xiàn)當前函數(shù)作用域中沒有n變量蝗蛙,則根據(jù)作用域鏈向上查找蝇庭。找到add的AO中有n變量。n++

num()執(zhí)行完成捡硅,出棧

image

num()執(zhí)行完成哮内。num的執(zhí)行上下文出棧。num的活動對象AO被垃圾回收壮韭。
接下來的num()執(zhí)行北发,和上述步驟相同。

到這里閉包函數(shù)是如何執(zhí)行也就解釋清楚了喷屋。

閉包的缺點

通過上面的分析琳拨。我們發(fā)現(xiàn)沒生成一個閉包就會有一個活動對象AO常駐內(nèi)存,不會被銷毀屯曹,所以有可能會導(dǎo)致內(nèi)存溢出狱庇。

如何取消閉包

通過上面的分析。我們發(fā)現(xiàn)生成閉包就是因為有一個循環(huán)引用恶耽。導(dǎo)致活動對象AO無法被銷毀垃圾回收密任。所以我們?nèi)绻胍∠]包,只需要打斷循環(huán)引用就好了: num = null偷俭。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末浪讳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子涌萤,更是在濱河造成了極大的恐慌淹遵,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件形葬,死亡現(xiàn)場離奇詭異合呐,居然都是意外死亡,警方通過查閱死者的電腦和手機笙以,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來冻辩,“玉大人猖腕,你說我怎么就攤上這事『奚粒” “怎么了倘感?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長咙咽。 經(jīng)常有香客問我老玛,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任蜡豹,我火速辦了婚禮麸粮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘镜廉。我一直安慰自己弄诲,他們只是感情好,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布娇唯。 她就那樣靜靜地躺著齐遵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪塔插。 梳的紋絲不亂的頭發(fā)上梗摇,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機與錄音想许,去河邊找鬼留美。 笑死,一個胖子當著我的面吹牛伸刃,可吹牛的內(nèi)容都是我干的谎砾。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼捧颅,長吁一口氣:“原來是場噩夢啊……” “哼景图!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碉哑,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤挚币,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后扣典,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體妆毕,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年贮尖,在試婚紗的時候發(fā)現(xiàn)自己被綠了笛粘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡湿硝,死狀恐怖薪前,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情关斜,我是刑警寧澤示括,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站痢畜,受9級特大地震影響垛膝,放射性物質(zhì)發(fā)生泄漏鳍侣。R本人自食惡果不足惜墨辛,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一萎庭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瑞妇,春花似錦扔罪、人聲如沸秉沼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽唬复。三九已至,卻和暖如春全肮,著一層夾襖步出監(jiān)牢的瞬間敞咧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工辜腺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留休建,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓评疗,卻偏偏與公主長得像测砂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子百匆,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

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

  • 下面就來說說閉包的一些基本概念和具體的形成過程砌些。 什么是閉包? 閉包就是既能重用一個變量加匈,又可以保護變量不被污染的...
    hans_431c閱讀 1,014評論 0 1
  • 一雕拼、閉包的定義 閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù) --《JavaScript高級程序設(shè)計》 函數(shù)對象...
    沐向閱讀 346評論 0 0
  • 文 / 景朝霞來源公號 / 朝霞的光影筆記ID / zhaoxiajingjing圖 / 自己畫 ????點個贊纵东,...
    鯨鯨景鯨叻閱讀 578評論 0 0
  • 前言 閉包是JS中重要的內(nèi)容,對大多數(shù)人來說都會覺的閉包本身很好理解啥寇,不就是一個函數(shù)嵌套一個函數(shù)嗎偎球?但是再深入解釋...
    蛙哇閱讀 989評論 0 1
  • 在前端開發(fā)中閉包是一個很重要的知識點,是面試中一定會被問到的內(nèi)容示姿。之前我對閉包的理解主要是"通過閉包可以在函數(shù)外部...
    CodeMT閱讀 176評論 0 0