今天我們學(xué)習(xí)了 Javascript 中作用域鏈和閉包的相關(guān)知識犁柜,在此寫一篇文章來總結(jié)一下洲鸠,加深自己對這兩個(gè)知識點(diǎn)的理解。
作用域鏈:
要了解作用域鏈,必須先明白執(zhí)行環(huán)境(execution context )扒腕,執(zhí)行環(huán)境定義了變量或函數(shù)有權(quán)訪問的其他數(shù)據(jù)绢淀。定義了他們的行為。每個(gè)執(zhí)行環(huán)境都有一個(gè)和它關(guān)聯(lián)的變量對象瘾腰,在這個(gè)執(zhí)行環(huán)境中的所有變量和函數(shù)都保存在這個(gè)對象中皆的。在web瀏覽器中,全局執(zhí)行環(huán)境的變量對象就是 window 對象蹋盆,所有的全局變量和函數(shù)都是 window 的屬性和方法祭务。而對于函數(shù)來說,變量對象就是這個(gè)函數(shù)的 活動(dòng)多象怪嫌。
作用域鏈與一個(gè)執(zhí)行環(huán)境相關(guān)义锥,作用域鏈用于在標(biāo)示符解析中變量查找。
函數(shù)也是對象岩灭,也擁有屬性和方法拌倍,每個(gè)函數(shù)中都有一個(gè)內(nèi)部屬性 [[ Scope ]],這個(gè)屬性指向函數(shù)的作用域鏈噪径。作用域鏈中儲存的是每個(gè)執(zhí)行環(huán)境中相關(guān)的變量對象柱恤。當(dāng)申明一個(gè)函數(shù),那么就會(huì)創(chuàng)建出這個(gè)函數(shù)的作用域鏈找爱,這個(gè)作用域鏈此時(shí)只包含一個(gè)變量對象梗顺,就是 window 對象。當(dāng)調(diào)用這個(gè)函數(shù)的時(shí)候车摄,會(huì)先創(chuàng)建一個(gè)執(zhí)行環(huán)境寺谤,這個(gè)執(zhí)行環(huán)境有自己的作用域鏈,作用域鏈里初始化為這個(gè)函數(shù)里所有的變量和對象吮播,再創(chuàng)建這個(gè)執(zhí)行環(huán)境相關(guān)的變量對象变屁,變量對象會(huì)儲存這個(gè)函數(shù)里所有的變量和對象。把變量對象儲存在作用域的頂端意狠,執(zhí)行函數(shù)時(shí)粟关,變量查找從作用域頂端開始查找,直到作用域的末端环戈。就形成了作用域鏈闷板。
請看下列代碼:
內(nèi)部函數(shù)的作用域圖:
閉包:
在上面的代碼中,createSumFunction函數(shù)返回了一個(gè)匿名函數(shù)院塞,而這個(gè)匿名函數(shù)使用了createSumFunction函數(shù)中的局部變量(參數(shù))遮晚,即使createSumFunction這個(gè)函數(shù)執(zhí)行結(jié)束了,由于作用域鏈的存在迫悠,他的局部變量在匿名函數(shù)中仍然可以使用鹏漆,這個(gè)匿名函數(shù)就是閉包。
閉包用一句簡單的話來描述:
閉包就是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。
閉包是一種特殊的對象艺玲。它是由函數(shù)和創(chuàng)建此函數(shù)的環(huán)境組成括蝠。環(huán)境由創(chuàng)造閉包時(shí)作用域中所有的局部變量組成。上面代碼中饭聚,sumFun就是一個(gè)閉包忌警,由匿名函數(shù)和創(chuàng)建閉包是所申明的num1 和num2兩個(gè)局部變量組成。
閉包的應(yīng)用:
請看下面代碼:
以上代碼中秒梳,雖然函數(shù)申明在num++之前法绵。但是函數(shù)調(diào)用的時(shí)候num 已經(jīng)++ 過了,所以最后的num值為6.由此可知:閉包中使用局部變量的值酪碘,一定是這個(gè)變量的最新值(最后的值)朋譬。
請看一下代碼:
此列是經(jīng)典的for循環(huán)問題。當(dāng)運(yùn)行的時(shí)候會(huì)發(fā)現(xiàn)兴垦,無論你點(diǎn)擊哪個(gè)按鈕徙赢,都是彈出 “我是底4個(gè)按鈕”,這就是閉包所導(dǎo)致的探越。因?yàn)樗?i 的值狡赐,總是最新的值。
解決方案:
好了钦幔,本次總結(jié)就到此結(jié)束了枕屉,因?yàn)閯倓倢W(xué)習(xí),總結(jié)得不好鲤氢,也不到位搀擂,希望各位能夠理解支持,也能把自己的建議告訴我铜异,我定積極進(jìn)取哥倔。