老生常談的Javascript作用域問題
在前端學(xué)習(xí)中,作用域這個(gè)問題一直被廣泛提起,什么是作用域,什么又是作用域鏈?在Javascript中,怎么去理解這些概念都是學(xué)好這門語言的關(guān)鍵,所以在學(xué)習(xí)前端開發(fā)的過程中,我需要也很有必要去學(xué)習(xí)和總結(jié)下javascript----作用域。
作用域并不難,但是去很少有人能稍微深入的解釋什么是作用域,知其然而不知其所以然顯然是遠(yuǎn)遠(yuǎn)不夠的,所以我們就深入淺出一下,
本片博文旨在深度去分析作用域,如有總結(jié)不到位之處,請(qǐng)讀者海涵并在評(píng)論區(qū)指出。
談到作用域就不得不談到一個(gè)名詞----執(zhí)行環(huán)境。什么叫執(zhí)行環(huán)境呢?
執(zhí)行環(huán)境是Javascript中最為重要的一個(gè)概念,它定義了變量或函數(shù)有權(quán)訪問其他數(shù)據(jù),決定了他們各自的行為。那么在每個(gè)執(zhí)行環(huán)境中都有一個(gè)叫做“變量對(duì)象”的object,執(zhí)行環(huán)境中的所有變量和函數(shù)都保存在這個(gè)對(duì)象中,這個(gè)object是無法被訪問到了,它只能在后臺(tái)被javascript解釋器訪問到。
瀏覽器在解析Javascript代碼的時(shí)候會(huì)為每個(gè)函數(shù)創(chuàng)建一個(gè)執(zhí)行環(huán)境,并在該執(zhí)行環(huán)境中生成一個(gè)變量對(duì)象來存儲(chǔ)變量和其內(nèi)部的函數(shù)。我們常常用到的window就是最外圍的執(zhí)行環(huán)境,也叫全局執(zhí)行環(huán)境,每個(gè)執(zhí)行環(huán)境的代碼執(zhí)行完成之后,該環(huán)境被銷毀,其中的變量對(duì)象也將被銷毀,而全局執(zhí)行環(huán)境只會(huì)在瀏覽器或網(wǎng)頁關(guān)閉的時(shí)候被銷毀,其他的執(zhí)行環(huán)境(或者內(nèi)部的)則為局部執(zhí)行環(huán)境(函數(shù))。
每個(gè)函數(shù)都有自己的執(zhí)行環(huán)境,那么當(dāng)代碼的執(zhí)行流進(jìn)入到一個(gè)函數(shù)時(shí),會(huì)將該執(zhí)行環(huán)境推入到一個(gè)環(huán)境棧中,在函數(shù)執(zhí)行完成之后又將其彈出,把對(duì)這個(gè)執(zhí)行環(huán)境的控制權(quán)交還給之前的執(zhí)行環(huán)境,當(dāng)代碼在一個(gè)執(zhí)行環(huán)境中執(zhí)行的時(shí)候,會(huì)將該環(huán)境中的變量對(duì)象連入到作用域鏈中。作用域鏈的作用就是保證對(duì)執(zhí)行環(huán)境中的有權(quán)訪問的變量和函數(shù)有序的訪問。說到這里,大家可能有些迷糊啦,那么就用點(diǎn)代碼和圖片來解釋下吧。
- //window scope
- var name0 = 'scope0'<p>console.log(name0) //這里可以訪問到name0
- function scope1(){<p>
- var name1 = 'scope1'<p> console.log(name0,name1) //這里可以訪問到name0,name1
- function scope2(){
- var name2 = 'scope2'<p> console.log(name0,name1,name2) //這里可以訪問到name0,name1,name2
- function scope3(){
- var name3 = 'scope3'<p> console.log(name0,name1,name2,name3) //這里可以訪問到name0,name1,name2,name3
- }
- }
- }
當(dāng)JS解釋器去執(zhí)行這段代碼的時(shí)候,會(huì)生成4個(gè)執(zhí)行環(huán)境,分別是window,scope1,scope2,scope3。然后再執(zhí)行JS代碼的時(shí)候,會(huì)把每個(gè)執(zhí)行環(huán)境推入到執(zhí)行棧中,并生成變量對(duì)象給連接到作用域鏈中(從上到下),***生成的作用域鏈就為:
window→scope1→scope2→scope3
對(duì)于每個(gè)執(zhí)行環(huán)境中的變量對(duì)象來說,它的作用域鏈就是它本生加上它之前的變量對(duì)象(例如scope2的作用域鏈就是scope2和它之前的 scope1和window)。我們先前說道,每個(gè)執(zhí)行環(huán)境中的變量對(duì)象就是該執(zhí)行環(huán)境能夠訪問到了變量和函數(shù),個(gè)人理解為這個(gè)函數(shù)就是變量對(duì)象的作用域 鏈上其他的變量對(duì)象,那么就很好理解了,我們分析下上面代碼scope2的變量對(duì)象上有哪些東西,首先是參數(shù)數(shù)組(arguments,這里為[])還有 name2變量,然后是scope1的變量對(duì)象和全局變量對(duì)象。
說了這么多,提了那么多概念和名詞,我們好像只是說到了作用域鏈,但是并沒有說到作用域,這不是扯淡嘛?。。。『冒?,我們現(xiàn)在就來談?wù)勛饔糜颉?/p>
還是先來扯下概念吧。是每個(gè)執(zhí)行環(huán)境可以通過作用域鏈向上訪問這個(gè)他的作用域鏈的其他執(zhí)行環(huán)境,但是不能向下訪問。這個(gè)就是作用域啦。。。
還是拿scope2函數(shù)來說吧,他可以訪問name2,name1,name0但是不能訪問name3,這個(gè)就是作用域的限定,他只能訪問到 scope1和window的執(zhí)行環(huán)境(還有它本身)。額,就這么一小段,我自己都醉了,但是個(gè)人覺得作用域就這點(diǎn)東西,關(guān)鍵的是在與對(duì)執(zhí)行環(huán)境、變量對(duì) 象和作用域鏈的理解。這些才是扎實(shí)的理解Javascript作用域的關(guān)鍵。
其實(shí)說到這里我感覺已經(jīng)差不多了,***次寫那么長的博文,文章水準(zhǔn)還有待提高,這篇文章主要是我在看《javascript高級(jí)程序設(shè)計(jì)》的看 到作用域這小節(jié),感覺作者寫了太好了,于是乎加上了一些個(gè)人的理解就寫了這篇博客。非常希望有對(duì)WEB開發(fā)有深刻理解的大大們提出批評(píng)和見解。