這篇文章主要介紹javascript作用域鏈與執(zhí)行環(huán)境的示例分析,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
創(chuàng)新互聯(lián)專注于企業(yè)成都全網(wǎng)營(yíng)銷、網(wǎng)站重做改版、建平網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5頁面制作、商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為建平等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
作用域、作用域鏈、執(zhí)行環(huán)境、執(zhí)行環(huán)境棧以及this的概念在javascript中非常重要,本人經(jīng)常弄混淆,這里梳理一下;
局部作用域函數(shù)內(nèi)部的區(qū)域,全局作用域就是window;
作用域鏈取決于函數(shù)被聲明時(shí)的位置,解析標(biāo)識(shí)符的時(shí)候就先找當(dāng)前作用域,再向外查找,直到全局,這樣一個(gè)順序;和函數(shù)在哪里調(diào)用無關(guān);
執(zhí)行環(huán)境就是函數(shù)可訪問的數(shù)據(jù)和變量的集合,也就是函數(shù)的作用域鏈上的所有數(shù)據(jù)和變量;
執(zhí)行環(huán)境棧就是根據(jù)代碼執(zhí)行順序,各執(zhí)行環(huán)境按照棧的形式逐層訪問,并且用完了退出來扔掉;如果當(dāng)前執(zhí)行環(huán)境(存放當(dāng)前作用域鏈里的數(shù)據(jù)和變量)找不到變量,那就是找不到了,不會(huì)往之前的那個(gè)執(zhí)行環(huán)境查找,它和作用域鏈?zhǔn)遣煌模?/p>
this是一個(gè)對(duì)象,它取決于是誰執(zhí)行的,誰執(zhí)行那就是誰;(this的概念還是不太清楚,這里寫的有點(diǎn)萬金油,過兩天再來修正)
作用域
JavaScript沒有塊級(jí)作用域的概念,只有函數(shù)級(jí)作用域:變量在聲明它們的函數(shù)體及其子函數(shù)內(nèi)是可見的。
作用域就是變量和函數(shù)的可訪問范圍,控制著變量和函數(shù)的可見性與生命周期,在JavaScript中變量的作用域有全局作用域和局部作用域。
變量沒有在函數(shù)內(nèi)聲明或者聲明的時(shí)候沒有帶var就是全局變量,擁有全局作用域;
全局變量可以當(dāng)做window對(duì)象的屬性用,他們是一樣的;
window對(duì)象的所有屬性擁有全局作用域,在代碼任何地方都可以訪問;
函數(shù)內(nèi)部聲明的變量就是局部變量,只能在函數(shù)體內(nèi)使用,函數(shù)的參數(shù)雖然沒有使用var但仍然是局部變量。
作用域鏈
作用域鏈取決于函數(shù)被聲明時(shí)的位置,解析標(biāo)識(shí)符的時(shí)候就先從當(dāng)前作用域開始找,在當(dāng)前作用域中無法找到時(shí),引擎就會(huì)在外層嵌套的作用域中繼續(xù)查找,直到找到該變量,或抵達(dá)最外層的作用域(也就是全局作用域)為止;它的路線已經(jīng)被定死了,和函數(shù)在哪里運(yùn)行無關(guān);
在多層的嵌套作用域中可以定義同名的標(biāo)識(shí)符,這叫作“遮蔽效應(yīng)”,內(nèi)部的標(biāo)識(shí)符“遮蔽”了外部的標(biāo)識(shí)符
通過window.a這種技術(shù)可以訪問那些被同名變量所遮蔽的全局變量。但非全局的變量如果被遮蔽了,無論如何都無法被訪問到;
執(zhí)行環(huán)境
執(zhí)行環(huán)境(execution context),也叫執(zhí)行上下文。每個(gè)執(zhí)行環(huán)境都有一個(gè)變量對(duì)象(variable object),保存函數(shù)可訪問的所有變量和數(shù)據(jù)(也就是函數(shù)的作用域鏈上的所有數(shù)據(jù)和變量)。我們的代碼訪問不到它,它是給引擎使用的;
執(zhí)行環(huán)境棧,當(dāng)執(zhí)行進(jìn)入一個(gè)函數(shù)時(shí),函數(shù)的執(zhí)行環(huán)境就會(huì)被推入一個(gè)棧中。而在函數(shù)執(zhí)行完之后,棧將其執(zhí)行環(huán)境移除,它里面的變量和數(shù)據(jù)會(huì)被標(biāo)記清除,等待垃圾回收,再把控制權(quán)返回給之前的執(zhí)行環(huán)境。javascript程序中的執(zhí)行正是由這個(gè)機(jī)制控制著;
需要注意的是如果當(dāng)前執(zhí)行環(huán)境(存放當(dāng)前作用域鏈里的數(shù)據(jù)和變量)找不到變量,那就是找不到了,不會(huì)往之前的那個(gè)執(zhí)行環(huán)境查找,和作用域鏈?zhǔn)遣灰粯拥模?/strong>
代碼的執(zhí)行順序也不全是一行一行的執(zhí)行,而是和函數(shù)的調(diào)用順序有關(guān):
代碼進(jìn)入全局執(zhí)行環(huán)境,全局執(zhí)行環(huán)境放入環(huán)境棧;
當(dāng)執(zhí)行到一個(gè)函數(shù)時(shí),就把這個(gè)函數(shù)的執(zhí)行環(huán)境推入到環(huán)境棧頂端,之前的執(zhí)行環(huán)境往后;
全局執(zhí)行環(huán)境最先進(jìn)入,所以一直在底端;就和棧的概念差不多;
函數(shù)執(zhí)行完之后,再把它的執(zhí)行環(huán)境從作用域鏈頂端移除,它保存的數(shù)據(jù)和函數(shù)都被標(biāo)記清除,等待垃圾回收;
控制權(quán)交給之前的執(zhí)行環(huán)境,繼續(xù)往下執(zhí)行;
當(dāng)頁面關(guān)閉時(shí),全局執(zhí)行環(huán)境才銷毀;
以上代碼的執(zhí)行順序:
代碼執(zhí)行進(jìn)入全局執(zhí)行環(huán)境,并對(duì)全局執(zhí)行環(huán)境中的代碼進(jìn)入聲明提升;
執(zhí)行第2行,賦值a=1; 然后第3行賦值b=2; 然后第4行賦值c=3; 然后第5行賦值d=4;
執(zhí)行第20行,調(diào)用outer(999)函數(shù),然后進(jìn)入outer(999)函數(shù)執(zhí)行環(huán)境,聲明提升,并將實(shí)參999傳給形參e;現(xiàn)在環(huán)境棧中有兩個(gè)執(zhí)行環(huán)境,outer(999)是當(dāng)前執(zhí)行環(huán)境;
執(zhí)行第16行,賦值a=5; 然后第17行賦值b=6;
執(zhí)行第18行,調(diào)用inner(7)函數(shù),然后進(jìn)入inner(7)函數(shù)執(zhí)行環(huán)境,聲明提升,并將實(shí)參7傳給形參d;
執(zhí)行第7行,賦值c=8; 然后運(yùn)算并輸出;
代碼優(yōu)化
由于在作用域鏈上查找變量是需要消耗性能的,我們應(yīng)該盡快的找到變量,所以在函數(shù)多層嵌套的時(shí)候,我們應(yīng)盡可能的使用函數(shù)內(nèi)部的局部變量;
我們?cè)诤瘮?shù)內(nèi)部使用全局變量可以說是一種跨作用域操作,如果某個(gè)跨作用域的值在函數(shù)的內(nèi)部被多次使用,那么我們就把它存儲(chǔ)到局部變量里,這樣可以提高性能。
以上是“javascript作用域鏈與執(zhí)行環(huán)境的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!