JavaScript基礎(chǔ)06- 作用域與預(yù)解析

作用域

通俗來(lái)講瓷耙,作用域是一個(gè)變量或函數(shù)的作用范圍。作用域在函數(shù)定義時(shí)妻怎,就已經(jīng)確定了壳炎。目的是為了提高程序的可靠性,減少命名沖突逼侦。

作用域的分類

  1. 全局作用域
  2. 局部作用域(函數(shù)作用域)

根據(jù)作用域的不同匿辩,變量可以分為兩類: 全局變量和局部變量

全局變量

  1. 在全局作用域下聲明的變量,叫「全局變量」榛丢。在全局作用域的任何一地方铲球,都可以訪問(wèn)這個(gè)變量。
  2. 在全局作用域下晰赞,使用 var 聲明的變量是全局變量稼病。
  3. 在函數(shù)內(nèi)不使用 var 聲明的變量也是全局變量(不建議這么用)。

局部變量

  1. 定義在函數(shù)作用域的變量掖鱼,叫「局部變量」然走。
  2. 在函數(shù)內(nèi)部,使用 var 聲明的變量是局部變量戏挡。
  3. 函數(shù)的形參也是屬于局部變量芍瑞。
    從執(zhí)行效率來(lái)看全局變量和局部變量:
  4. 全局變量:只有瀏覽器關(guān)閉時(shí)才會(huì)被銷毀,比較占內(nèi)存褐墅。
  5. 局部變量:當(dāng)其所在的代碼塊運(yùn)行結(jié)束后拆檬,就會(huì)被銷毀,比較節(jié)約內(nèi)存空間妥凳。

作用域鏈

只有函數(shù)可以制造作用域結(jié)構(gòu)竟贯, 那么只要是代碼坝锰,就至少有一個(gè)作用域, 即全局作用域蔫饰。凡是代碼中有函數(shù)狈惫,那么這個(gè)函數(shù)就構(gòu)成另一個(gè)作用域捅位。如果函數(shù)中還有函數(shù)降传,那么在這個(gè)作用域中就又可以誕生一個(gè)作用域纠永。將這樣的所有的作用域列出來(lái)嚣鄙,可以有一個(gè)結(jié)構(gòu): 函數(shù)內(nèi)指向函數(shù)外的鏈?zhǔn)浇Y(jié)構(gòu)允蜈。就稱作作用域鏈磷箕。

  1. 當(dāng)在函數(shù)作用域操作一個(gè)變量時(shí)选酗,它會(huì)先在自身作用域中尋找,如果有就直接使用(就近原則)岳枷。如果沒(méi)有則向上一級(jí)作用域中尋找芒填,直到找到全局作用域;如果全局作用域中依然沒(méi)有找到空繁,則會(huì)報(bào)錯(cuò)殿衰。
  2. 在函數(shù)中要訪問(wèn)全局變量可以使用window對(duì)象。(比如說(shuō)盛泡,全局作用域和函數(shù)作用域都定義了變量a闷祥,如果想訪問(wèn)全局變量,可以使用window.a)
  3. 全局作用域在頁(yè)面打開(kāi)時(shí)創(chuàng)建傲诵,在頁(yè)面關(guān)閉時(shí)銷毀凯砍。
  4. 在全局作用域中有一個(gè)全局對(duì)象window,它代表的是一個(gè)瀏覽器的窗口拴竹,由瀏覽器創(chuàng)建悟衩,我們可以直接使用。全局作用域創(chuàng)建的變量都會(huì)作為window對(duì)象的屬性保存栓拜。比如在全局作用域內(nèi)寫(xiě) var a = 100座泳,這里的 a 等價(jià)于 window.a。創(chuàng)建的函數(shù)都會(huì)作為window對(duì)象的方法保存幕与。

預(yù)解析

JavaScript代碼的執(zhí)行是由瀏覽器中的JavaScript解析器來(lái)執(zhí)行的挑势。JavaScript解析器執(zhí)行JavaScript代碼的時(shí)候,分為兩個(gè)過(guò)程:預(yù)解析過(guò)程和代碼執(zhí)行過(guò)程

預(yù)解析過(guò)程

  1. 把變量的聲明提升到當(dāng)前作用域的最前面纽门,只會(huì)提升聲明薛耻,不會(huì)提升賦值。
  2. 把函數(shù)的聲明提升到當(dāng)前作用域的最前面赏陵,只會(huì)提升聲明饼齿,不會(huì)提升調(diào)用。
  3. 先提升var蝙搔,在提升function

變量的聲明提前

使用var關(guān)鍵字聲明的變量( 比如 var a = 1)缕溉,會(huì)在所有的代碼執(zhí)行之前被聲明(但是不會(huì)賦值),但是如果聲明變量時(shí)不是用var關(guān)鍵字(比如直接寫(xiě)a = 1)吃型,則變量不會(huì)被聲明提前证鸥。
所以,既然JS中存在變量提升的現(xiàn)象,那么枉层,在實(shí)戰(zhàn)開(kāi)發(fā)中泉褐,為了避免出錯(cuò),建議先聲明一個(gè)變量鸟蜡,然后再使用這個(gè)變量膜赃。

函數(shù)的聲明提前

使用函數(shù)聲明的形式創(chuàng)建的函數(shù)function foo(){},會(huì)被聲明提前揉忘。也就是說(shuō)跳座,整個(gè)函數(shù)會(huì)在所有的代碼執(zhí)行之前就被創(chuàng)建完成。所以泣矛,在代碼順序里疲眷,我們可以先調(diào)用函數(shù),再定義函數(shù)您朽。

 fn1();  // 雖然 函數(shù) fn1 的定義是在后面狂丝,但是因?yàn)楸惶崆奥暶髁耍?所以此處可以調(diào)用函數(shù)
    function fn1() {
        console.log('上邊兒調(diào)用的時(shí)候,函數(shù)聲明已經(jīng)被提前了');
    }

使用函數(shù)表達(dá)式創(chuàng)建的函數(shù)var foo = function(){}虚倒,不會(huì)被聲明提前美侦,所以不能在聲明前調(diào)用。

函數(shù)表達(dá)式

函數(shù)作用域

  1. 函數(shù)中魂奥,使用var關(guān)鍵字聲明的變量菠剩,會(huì)在函數(shù)中所有的代碼執(zhí)行之前被聲明。
  2. 函數(shù)中耻煤,沒(méi)有var聲明的變量都是全局變量具壮,而且并不會(huì)提前聲明。

注意哈蝇,定義形參就相當(dāng)于在函數(shù)作用域中聲明了變量棺妓。

 function fun(e) { // 這個(gè)函數(shù)中,因?yàn)橛辛诵螀?e炮赦,此時(shí)就相當(dāng)于在函數(shù)內(nèi)部的第一行代碼里怜跑,寫(xiě)了 var e;
        console.log(e);
    }

函數(shù)預(yù)編譯步驟

預(yù)編譯四部曲:

  1. 函數(shù)在運(yùn)行的瞬間,生成一個(gè)執(zhí)行期上下文 (Active Object)吠勘,簡(jiǎn)稱AO性芬;
  2. 分析參數(shù)
    2.1 函數(shù)接收形式參數(shù),添加到AO的屬性剧防,并且這個(gè)時(shí)候值為undefine,例如AO.age=undefined;
    2.2 接收實(shí)參植锉,添加到AO的屬性,覆蓋之前的undefined;
  3. 分析變量聲明峭拘,如var age;或var age=23;
    3.1 如果上一步分析參數(shù)中AO還沒(méi)有age屬性俊庇,則添加AO屬性為undefined狮暑,即AO.age=undefined;
    3.2 如果AO上面已經(jīng)有age屬性了,則不作任何修改;
  4. 分析函數(shù)的聲明辉饱,如果有function age(){}搬男;把函數(shù)賦給AO.age ,覆蓋上一步分析的值;
函數(shù)預(yù)編譯

執(zhí)行期上下文:
當(dāng)函數(shù)執(zhí)行時(shí),會(huì)創(chuàng)建一個(gè)稱為執(zhí)行期上下文的內(nèi)部對(duì)象鞋囊。一個(gè)執(zhí)行期上下文定義了一個(gè)函數(shù)執(zhí)行時(shí)的環(huán)境止后,函數(shù)每次執(zhí)行時(shí)對(duì)應(yīng)的執(zhí)行上下文都是獨(dú)一無(wú)二的,所以多次調(diào)用一個(gè)函數(shù)會(huì)導(dǎo)致多個(gè)執(zhí)行上下文溜腐,當(dāng)函數(shù)執(zhí)行完畢,它所產(chǎn)生的執(zhí)行上下文被銷毀

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瓜喇,一起剝皮案震驚了整個(gè)濱河市挺益,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乘寒,老刑警劉巖望众,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異伞辛,居然都是意外死亡烂翰,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)蚤氏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)甘耿,“玉大人,你說(shuō)我怎么就攤上這事竿滨〖烟瘢” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵于游,是天一觀的道長(zhǎng)毁葱。 經(jīng)常有香客問(wèn)我,道長(zhǎng)贰剥,這世上最難降的妖魔是什么倾剿? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮蚌成,結(jié)果婚禮上前痘,老公的妹妹穿的比我還像新娘。我一直安慰自己笑陈,他們只是感情好际度,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著涵妥,像睡著了一般乖菱。 火紅的嫁衣襯著肌膚如雪坡锡。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,679評(píng)論 1 305
  • 那天窒所,我揣著相機(jī)與錄音鹉勒,去河邊找鬼。 笑死吵取,一個(gè)胖子當(dāng)著我的面吹牛禽额,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播皮官,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼脯倒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了捺氢?” 一聲冷哼從身側(cè)響起藻丢,我...
    開(kāi)封第一講書(shū)人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎摄乒,沒(méi)想到半個(gè)月后悠反,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡馍佑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年斋否,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拭荤。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茵臭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出穷劈,到底是詐尸還是另有隱情笼恰,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布歇终,位于F島的核電站社证,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏评凝。R本人自食惡果不足惜追葡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奕短。 院中可真熱鬧宜肉,春花似錦、人聲如沸翎碑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)日杈。三九已至遣铝,卻和暖如春佑刷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背酿炸。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工瘫絮, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人填硕。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓麦萤,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親扁眯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子壮莹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355