再學JS--閉包

MDN對閉包的定義:

閉包是指那些能夠訪問自由變量的函數(shù)

那什么是自由變量?

自由變量是指在函數(shù)中使用的运挫,但既不是函數(shù)參數(shù)也不是函數(shù)的局部變量的變量

所有旗们,閉包 = 函數(shù) + 函數(shù)能訪問到的自由變量

例如:

var a = 1
function foo() {
    console.log(a)
}
foo()

foo函數(shù)可以訪問變量a廷痘,但是a既不是函數(shù)參數(shù)也不是foo函數(shù)的局部變量,所有a是局部變量件已。

所以foo函數(shù)+ foo函數(shù)能訪問的自由變量a就構成了一個閉包笋额,但是和以前理解的閉包不太一樣。

上述說的閉包是理論閉包篷扩,其實還有一個實踐角度上的閉包:

ECMAScript中兄猩,閉包是指

1、從理論角度:所有的函數(shù)鉴未。因為它們都在創(chuàng)建的時候就將上層的上下文的數(shù)據(jù)保存起來了枢冤。哪怕是簡單的全局變量也是如此,因為函數(shù)中訪問全局變量就相當于是在訪問自由變量铜秆,這個時候使用為外層的作用域淹真。

2、從實踐角度:以下函數(shù)才算是閉包:

(1)即使創(chuàng)建它的上下文已經(jīng)銷毀连茧,它既然存在(比如核蘸,內部函數(shù)從父函數(shù)中返回)

(2)在代碼中引用了自由變量

分析

var scope = 'global scope'
function checkscope() {
    var scope = 'local scope'
    function f() {
        return scope
    }
    return f
}
var foo = checkscope()
foo()

分析下上述代碼的執(zhí)行過程:

  1. 進入全局代碼,創(chuàng)建全局執(zhí)行上下文啸驯,全局執(zhí)行上下文壓入執(zhí)行上下文棧
  2. 全局執(zhí)行上下文初始化
  3. 執(zhí)行checkscope函數(shù)客扎,創(chuàng)建checkscope函數(shù)執(zhí)行上下文,checkscope執(zhí)行上下文被壓入執(zhí)行上下文棧
  4. checkscope執(zhí)行上下文初始化坯汤,創(chuàng)建變量對象虐唠、作用域鏈、this
  5. checkscope函數(shù)執(zhí)行完畢惰聂,checkscope執(zhí)行上下文從執(zhí)行上下文棧中彈出
  6. 執(zhí)行f函數(shù)疆偿,創(chuàng)建f函數(shù)執(zhí)行上下文,f執(zhí)行上下文被壓入執(zhí)行上下文棧
  7. f執(zhí)行上下文初始化搓幌,創(chuàng)建變量對象杆故、作用域鏈、this
  8. f函數(shù)執(zhí)行完畢溉愁,f函數(shù)上下文從執(zhí)行上下文棧中彈出

當了解了上述的過程之后处铛,我們會發(fā)現(xiàn)一個問題,當f函數(shù)執(zhí)行的時候拐揭,checkscope函數(shù)上下文已經(jīng)被銷毀了(執(zhí)行上下文棧中彈出)撤蟆,怎么還能讀取到checkscope中的scope的值呢?

當我們了解了具體的執(zhí)行過程后堂污,我們知道f執(zhí)行上下文維護了一個作用域鏈:

fContext={
    Scope: [AO, checkscopeContext.AO, globalContext.VO]
}

就是因為這個作用域鏈家肯,f函數(shù)依然可以讀取到checkscopeContext.AO的值,說明當f函數(shù)引用了checkscopeContext.AO中的值的時候盟猖,即使checkscopeContext被銷毀了讨衣,但是JavaScript依然迥然checkscopeContext.AO活在內存中换棚,f函數(shù)依然可以通過f函數(shù)的作用域鏈找到它,正是因為JavaScript做到了這一點反镇,從而實現(xiàn)了閉包這個概念固蚤。

必刷題分析

var data = []
for(var i=0;i<3;i++) {
    data[i] = function() {
        console.log(i)
    }
}
data[0]()
data[1]()
data[2]()

答案都是3,來分析一個原因

當執(zhí)行到data[0]之前歹茶,此時的全局上下文VO為:

globalContext ={
    VO: {
        data: [...],
        i: 3
    }
}

當執(zhí)行data[0]函數(shù)的時候夕玩,data[0]函數(shù)的作用域鏈為:

data[0]Context: {
    Scope: [AO, globalContext.VO]
}

data[0]Context的AO并沒有i的值,所以會從globalContext.VO中去找辆亏,i為3风秤,所以打印結果為3

來看看閉包的實現(xiàn)方式:

var data = []
for(var i=0;i<3;i++) {
    data[i] = (function(i) {
        return function() {
            console.log(i)
        }
    })(i)
}
data[0]()
data[1]()
data[2]()

當執(zhí)行data[0]函數(shù)的時候鳖目,data[0]函數(shù)的作用域鏈為:

data[0]Context: {
    Scope: [AO, 匿名函數(shù)Context.VO, globalContext.VO]
}

匿名函數(shù)執(zhí)行上下文的AO為:

匿名函數(shù)Context = {
    AO: {
        arguments: {
            0: 0,
            lenght: 1
        },
        i: 0
    }
}

data[0]Context的AO并沒有i值扮叨,所有會沿著作用域鏈從匿名函數(shù)Context.AO中查找,這時候就會找i為0领迈,找到了就不會往globalContext.VO中查找了彻磁,即使globalContext.VO也有i的值(值為3),所有打印為0

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末狸捅,一起剝皮案震驚了整個濱河市衷蜓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌尘喝,老刑警劉巖磁浇,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異朽褪,居然都是意外死亡置吓,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門缔赠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來衍锚,“玉大人,你說我怎么就攤上這事嗤堰〈髦剩” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵踢匣,是天一觀的道長告匠。 經(jīng)常有香客問我,道長离唬,這世上最難降的妖魔是什么后专? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮男娄,結果婚禮上行贪,老公的妹妹穿的比我還像新娘漾稀。我一直安慰自己,他們只是感情好建瘫,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布崭捍。 她就那樣靜靜地躺著,像睡著了一般啰脚。 火紅的嫁衣襯著肌膚如雪殷蛇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天橄浓,我揣著相機與錄音粒梦,去河邊找鬼。 笑死荸实,一個胖子當著我的面吹牛匀们,可吹牛的內容都是我干的。 我是一名探鬼主播准给,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼泄朴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了露氮?” 一聲冷哼從身側響起祖灰,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎畔规,沒想到半個月后局扶,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡叁扫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年三妈,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陌兑。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡沈跨,死狀恐怖,靈堂內的尸體忽然破棺而出兔综,到底是詐尸還是另有隱情饿凛,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布软驰,位于F島的核電站涧窒,受9級特大地震影響,放射性物質發(fā)生泄漏锭亏。R本人自食惡果不足惜纠吴,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望慧瘤。 院中可真熱鬧戴已,春花似錦固该、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至握联,卻和暖如春桦沉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背金闽。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工纯露, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人代芜。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓埠褪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蜒犯。 傳聞我的和親對象是個殘疾皇子组橄,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內容

  • 定義 MDN 對閉包的定義為: 閉包是指那些能夠訪問自由變量的函數(shù)。 那什么是自由變量呢罚随? 自由變量是指在函數(shù)中使...
    如果俞天陽會飛閱讀 193評論 0 0
  • JavaScript深入系列第八篇,介紹理論上的閉包和實踐上的閉包羽资,以及從作用域鏈的角度解析經(jīng)典的閉包題淘菩。 定義 ...
    Vicky丶Amor閱讀 433評論 0 5
  • 作用域鏈與閉包 了解作用域鏈之前需要先了解下作用域是什么。 作用域 幾乎所有的語言都有作用域的概念屠升。這是因為它們都...
    周二可閱讀 523評論 1 2
  • 原文出處 JavaScript深入之閉包 定義 MDN 對閉包的定義為: 閉包是指那些能夠訪問自由變量的函數(shù)潮改。 那...
    怪物獵人閱讀 197評論 0 0
  • ? 文 :葉 大 帥 哥 ?插畫:納 什 男 爵 空白布局 36 的 大 寶 空白布局 那 些 空白布局 空白布局...
    暴風小隊閱讀 371評論 0 0