JavaScript淺析 -- 作用域和作用域鏈

一懒棉、作用域

所謂作用域,簡單來說就是變量和函數(shù)的可訪問范圍该抒。舉個(gè)例子:

function test() {
    var a = 1;
    console.log(a); // 輸出1
}
console.log(a); // 會(huì)報(bào)錯(cuò)慌洪,找不到a

上面test函數(shù)中的變量a擁有一個(gè)函數(shù)作用域,只能在函數(shù)里可以訪問到凑保,但在函數(shù)外面console.log(a)則訪問不到會(huì)報(bào)錯(cuò)冈爹。

JS有兩個(gè)作用域,全局作用域和局部作用域(又叫函數(shù)作用域)欧引。

  1. 局部作用域:只在某個(gè)特定的代碼塊里才能訪問频伤。比如開頭的例子變量a,只能在函數(shù)包裹起來的那塊內(nèi)部區(qū)域里能被訪問维咸。常見于函數(shù)內(nèi)部,如下的形式中從 ‘{’ 開始到與之匹配的 ‘}’ 結(jié)束惠爽,for癌蓖、if、switch等包裹起來的不算婚肆。
function test() { 
    // 局部作用域
}
或者
var test = function() {
    // 局部作用域
}
  1. 全局作用域:在代碼中所有地方都能夠訪問其中變量和函數(shù)的作用范圍租副。有下面三種情況可以擁有全局作用域:
  • 最外層函數(shù)和最外層函數(shù)之外定義的變量擁有全局作用域。
  • 未定義直接賦值的對象自動(dòng)變?yōu)槿肿兞拷闲裕瑩碛腥肿饔糜颉?/li>
  • window對象的所有屬性擁有全局作用域用僧。

二、作用域鏈

在講作用域鏈前赞咙,我們先來講講變量對象责循。

  • 變量對象:每個(gè)函數(shù)都有自己的執(zhí)行環(huán)境,每個(gè)環(huán)境都有與之關(guān)聯(lián)的變量對象攀操,執(zhí)行環(huán)境中定義的變量和函數(shù)都保存在這個(gè)對象中院仿。由于在同個(gè)執(zhí)行環(huán)境里定義的變量和函數(shù)擁有相同的作用域,所以同個(gè)變量對象里保存的變量和函數(shù)擁有相同的作用域速和。(在web瀏覽器中歹垫,全局執(zhí)行環(huán)境對應(yīng)的變量對象為window對象,所以如上面所說window對象的屬性才會(huì)有全局作用域)颠放。

而代碼在環(huán)境中執(zhí)行時(shí)排惨,會(huì)創(chuàng)建變量對象的一個(gè)作用域鏈。作用域鏈的前端碰凶,是當(dāng)前執(zhí)行代碼所在環(huán)境的變量對象暮芭,然后是包含環(huán)境(即當(dāng)前函數(shù)所在的執(zhí)行環(huán)境)的變量對象鹿驼,一直延續(xù)到全局執(zhí)行環(huán)境,即全局環(huán)境的變量對象始終是作用域鏈中的最后一個(gè)對象谴麦。舉個(gè)例子:

var outVariable = '最外層變量';
function outFunction() { // 最外層函數(shù)
    var innerVariable = '內(nèi)部變量';
    function innerFunction() { // 內(nèi)部函數(shù)
        var variable = '內(nèi)部函數(shù)的變量';
    } 
}

上面這個(gè)例子蠢沿,在inner函數(shù)的執(zhí)行環(huán)境中的作用域鏈如下:

作用域鏈

由圖可以看到,作用域鏈的開頭是當(dāng)前執(zhí)行代碼所在環(huán)境的變量對象匾效,末尾是全局變量對象舷蟀。

那作用域鏈有什么用?作用域鏈的用途面哼,是保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問野宜。要理解這句話,重點(diǎn)在于理解有權(quán)和有序這兩個(gè)字魔策。

  • 有權(quán):只有在當(dāng)前執(zhí)行環(huán)境的作用域鏈上變量對象的變量和函數(shù)才能訪問到匈子。
  • 有序:當(dāng)查找一個(gè)變量時(shí),先在當(dāng)前的變量對象里找闯袒,找不到再到作用域鏈的上一個(gè)變量對象中找虎敦,一直到作用域鏈的末尾即全局變量對象,如果還沒有則報(bào)錯(cuò)政敢。
var outVariable = '最外層變量';
function outFunction() {
    function firstFunc() {
        var firstFuncVariable = '第一個(gè)函數(shù)的變量';
        console.log(outVariable); // 輸出'最外層變量'
    } 
    function secondFunc() {
        var secondFuncVariable = '第二個(gè)函數(shù)的變量';
        console.log(firstFuncVariable); // 報(bào)錯(cuò)
    }
}

這段代碼中函數(shù)firstFunc和函數(shù)secondFunc的作用域鏈分別為:

作用域鏈例子

根據(jù)上圖其徙,當(dāng)?shù)谝粋€(gè)函數(shù)要訪問outVariable變量時(shí),先找1里有沒有喷户,沒有再找2里也沒有唾那,再找3找到outVariable則返回。而第二個(gè)函數(shù)要訪問firstFuncVariable時(shí)褪尝,先找4沒有闹获,再找5沒有,最后找到6還沒有所以報(bào)錯(cuò)河哑,這個(gè)一層一層的搜索就是沿著作用域鏈的順序來的避诽。而secondFunc的作用域鏈上并沒有firstFunc的變量對象,所以無權(quán)訪問其中的變量璃谨。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末茎用,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子睬罗,更是在濱河造成了極大的恐慌轨功,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,207評論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件容达,死亡現(xiàn)場離奇詭異古涧,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)花盐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評論 3 400
  • 文/潘曉璐 我一進(jìn)店門羡滑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來菇爪,“玉大人,你說我怎么就攤上這事柒昏〉手妫” “怎么了?”我有些...
    開封第一講書人閱讀 170,031評論 0 366
  • 文/不壞的土叔 我叫張陵职祷,是天一觀的道長氏涩。 經(jīng)常有香客問我,道長有梆,這世上最難降的妖魔是什么是尖? 我笑而不...
    開封第一講書人閱讀 60,334評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮泥耀,結(jié)果婚禮上饺汹,老公的妹妹穿的比我還像新娘。我一直安慰自己痰催,他們只是感情好兜辞,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,322評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著夸溶,像睡著了一般逸吵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蜘醋,一...
    開封第一講書人閱讀 52,895評論 1 314
  • 那天胁塞,我揣著相機(jī)與錄音咏尝,去河邊找鬼压语。 笑死,一個(gè)胖子當(dāng)著我的面吹牛编检,可吹牛的內(nèi)容都是我干的胎食。 我是一名探鬼主播,決...
    沈念sama閱讀 41,300評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼允懂,長吁一口氣:“原來是場噩夢啊……” “哼厕怜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蕾总,我...
    開封第一講書人閱讀 40,264評論 0 277
  • 序言:老撾萬榮一對情侶失蹤粥航,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后生百,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體递雀,經(jīng)...
    沈念sama閱讀 46,784評論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,870評論 3 343
  • 正文 我和宋清朗相戀三年蚀浆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了缀程。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搜吧。...
    茶點(diǎn)故事閱讀 40,989評論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖杨凑,靈堂內(nèi)的尸體忽然破棺而出滤奈,到底是詐尸還是另有隱情,我是刑警寧澤撩满,帶...
    沈念sama閱讀 36,649評論 5 351
  • 正文 年R本政府宣布蜒程,位于F島的核電站,受9級(jí)特大地震影響鹦牛,放射性物質(zhì)發(fā)生泄漏搞糕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,331評論 3 336
  • 文/蒙蒙 一曼追、第九天 我趴在偏房一處隱蔽的房頂上張望窍仰。 院中可真熱鬧,春花似錦礼殊、人聲如沸驹吮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,814評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽碟狞。三九已至,卻和暖如春婚陪,著一層夾襖步出監(jiān)牢的瞬間族沃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,940評論 1 275
  • 我被黑心中介騙來泰國打工泌参, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留脆淹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,452評論 3 379
  • 正文 我出身青樓沽一,卻偏偏與公主長得像盖溺,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子铣缠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,995評論 2 361

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