變量作用域和變量提升

先來看這么一段代碼

var a = 1

function foo() {
    if(false){
        var a = 1
    }
    console.log('a:'+a);//a = undefined
}

foo()

為什么會這樣? if條件語句明明就沒有執(zhí)行眯杏,我們打印的應該是全局變量a才對匾乓。

其實很簡單,首先要知道js查詢變量的機制鳄厌。

下面給出《javascript高級程序設(shè)計3》中的解釋荞胡。

當在某個環(huán)境中為了讀取或?qū)懭攵靡粋€標識符時,必須通過搜索來確定該標識符實際代表什么了嚎。搜索過程從作用域鏈的前端開始泪漂,向上逐級查詢與給定名字匹配的標識符廊营。如果在局部環(huán)境中找到了該標識符,搜索過程停止萝勤,變量就緒露筒。如果在局部環(huán)境中沒有找到該變量名,則繼續(xù)沿作用域鏈向上搜索敌卓。搜索過程將一直追溯到全局環(huán)境的變量對象邀窃。如果在全局環(huán)境中也沒有找到這個標識符,則意味著該變量尚未聲明假哎。

通過下面這個示例瞬捕,可以理解查詢標識符的過程

var color = "blue";

function getColor(){

return color;

}

alert(getColor()); //"blue"

調(diào)用本例中的函數(shù)getColor()時會引用變量color。為了確定變量color 的值舵抹,將開始一個兩步的搜索過程肪虎。首先,搜索getColor()的變量對象惧蛹,查找其中是否包含一個名為color 的標識符扇救。在沒有找到的情況下,搜索繼續(xù)到下一個變量對象(全局環(huán)境的變量對象)香嗓,然后在那里找到了名為color 的標識符迅腔。因為搜索到了定義這個變量的變量對象,搜索過程宣告結(jié)束靠娱。
在這個搜索過程中沧烈,如果存在一個局部的變量的定義,則搜索會自動停止像云,不再進入另一個變量對象锌雀。換句話說,如果局部環(huán)境中存在著同名標識符迅诬,就不會使用位于父環(huán)境中的標識符腋逆,如下面的例子所示:

var color = "blue";

function getColor(){

var color = "red";

return color;

}

alert(getColor()); //"red"

修改后的代碼在getColor()函數(shù)中聲明了一個名為color 的局部變量。調(diào)用函數(shù)時侈贷,該變量就會被聲明惩歉。而當函數(shù)中的第二行代碼執(zhí)行時,意味著必須找到并返回變量color 的值俏蛮。搜索過程首先從局部環(huán)境中開始撑蚌,而且在這里發(fā)現(xiàn)了一個名為color 的變量,其值為"red"嫁蛇。因為變量已經(jīng)找到了锨并,所以搜索即行停止,return 語句就使用這個局部變量睬棚,并為函數(shù)會返回"red"。也就是說,任何位于局部變量color 的聲明之后的代碼抑党,如果不使用window.color 都無法訪問全局color變量包警。

好,到這里問題又來了底靠,開始例子中并沒有聲明局部變量a昂蕖(if條件語句永遠不執(zhí)行),那為什么仍然訪問不到?

這里要引入變量提升的概念暑中。先看一段代碼

console.log('a:'+a)//a:undefined

var a = 1

console.log('a:'+a)//a:1

實際上壹瘟,JavaScript 中,變量可以在使用后聲明鳄逾,也就是變量可以先使用再聲明稻轨。

變量提升:函數(shù)聲明和變量聲明總是會被解釋器悄悄地被"提升"到方法體的最頂部。
但JavaScript 只有聲明的變量會提升雕凹,初始化的不會殴俱。
所以這也是為什么沒有報錯,但a卻是undefined而不是1的原因枚抵。

這段代碼可以等效于這樣

var a

console.log('a:'+a)// a:undefined

a = 1

console.log('a:'+a)//a:1

好啦线欲,知道了這個后,上面那個問題就很簡單了汽摹。

實際上李丰,雖然if條件語句里的代碼并沒有執(zhí)行,但解釋器一開始就會進行變量提升逼泣。等效于這樣:

var a = 1

function foo() {
    var a
    if(false){
         a = 1
    }
    console.log('a:'+a);//a = undefined
}

foo()

由于變量提升嫌套,在函數(shù)里就已經(jīng)搜索到了局部變量a,繼而停止搜索圾旨。所以最終無法獲取全局變量a踱讨,出現(xiàn)問題。

PS:從這里可以看出砍的,變量提升這個功能是為了防止某些錯誤的發(fā)生而遷就了開發(fā)者痹筛,但實際上,這個功能可能反而是不利的

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末廓鞠,一起剝皮案震驚了整個濱河市帚稠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌床佳,老刑警劉巖滋早,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異砌们,居然都是意外死亡杆麸,警方通過查閱死者的電腦和手機搁进,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昔头,“玉大人饼问,你說我怎么就攤上這事〗腋” “怎么了莱革?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長讹开。 經(jīng)常有香客問我盅视,道長,這世上最難降的妖魔是什么旦万? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任闹击,我火速辦了婚禮,結(jié)果婚禮上纸型,老公的妹妹穿的比我還像新娘拇砰。我一直安慰自己,他們只是感情好狰腌,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布除破。 她就那樣靜靜地躺著,像睡著了一般琼腔。 火紅的嫁衣襯著肌膚如雪瑰枫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天丹莲,我揣著相機與錄音光坝,去河邊找鬼。 笑死甥材,一個胖子當著我的面吹牛盯另,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播洲赵,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼鸳惯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了叠萍?” 一聲冷哼從身側(cè)響起芝发,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎苛谷,沒想到半個月后辅鲸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡腹殿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年独悴,在試婚紗的時候發(fā)現(xiàn)自己被綠了例书。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡绵患,死狀恐怖雾叭,靈堂內(nèi)的尸體忽然破棺而出悟耘,到底是詐尸還是另有隱情落蝙,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布暂幼,位于F島的核電站筏勒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏旺嬉。R本人自食惡果不足惜管行,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望邪媳。 院中可真熱鬧捐顷,春花似錦、人聲如沸雨效。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽徽龟。三九已至叮姑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間据悔,已是汗流浹背传透。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留极颓,地道東北人朱盐。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像菠隆,于是被迫代替她去往敵國和親兵琳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361

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