JS中的變量提升

js和其他語言一樣嚷堡,都要經(jīng)歷編譯和執(zhí)行階段尸变。而js在編譯階段的時候义图,會搜集所有的變量聲明并且提前聲明變量,而其他的語句都不會改變他們的順序召烂,因此碱工,在編譯階段的時候,第一步就已經(jīng)執(zhí)行了奏夫,而第二步則是在執(zhí)行階段執(zhí)行到該語句的時候才執(zhí)行

也就是說怕篷,在編譯的時候,頁面上所有的變量都已經(jīng)被聲明了酗昼,但是都還沒有賦值廊谓,即數(shù)據(jù)類型暫為undefined。

例1

a = 5
var a
console.log(a)

那么這里會打印出什么呢麻削?按照正常的從上到下的邏輯思路蒸痹,第2行的a并沒有被定義舔示,所以第四行打印a時應(yīng)該會報錯說 a is not defined,但是电抚,注意注意,這里的a被提升了竖共。

“變量提升會將當(dāng)前作用域的所有變量的聲明提升到程序的頂部”蝙叛,意思就是說,雖然在第2行的a沒有用關(guān)鍵字 var 定義公给,但是編譯時會查找所有的var借帘,把它們放到該作用域的最頂部,相當(dāng)于以下的代碼執(zhí)行過程:

var a
a = 5
console.log(a)

例2

console.log(a)
a = 5
var a

是不是跟例1很像淌铐?只不過把賦值語句跟打印語句調(diào)換了一下位置肺然。那么現(xiàn)在第2行的執(zhí)行結(jié)果是打印出什么呢?結(jié)果是 undefined腿准〖势穑回憶一下變量提升的操作,把所有的var都提到最頂部吐葱,在這里就是把 var a 放到最開頭街望,接下來就是console.log(a),很明顯弟跑,這里的a還沒被賦值灾前,是在打印語句之后才被賦值,所以孟辑,已定義但未賦值的變量的數(shù)據(jù)類型是undefined哎甲,所以打印結(jié)果是undefined。
理解到簡單的定義之后饲嗽,就要思考一下相對比較復(fù)雜的變量提升了炭玫,我們結(jié)合函數(shù)來看看

第一種情況:函數(shù)有參數(shù),且與函數(shù)內(nèi)部的變量同名

function show(a){
    console.log(a);//10
    var a=20
    console.log(a);//20
    }
show(10)

開始學(xué)函數(shù)參數(shù)的時候貌虾,老師跟我們說础嫡,形參就相當(dāng)于是在函數(shù)內(nèi)部定義了一個變量,就是var 了一個變量酝惧;然后實參傳進來就相當(dāng)于是給這個變量賦了值榴鼎。接下來我們就可以沿著這個思路去分析。還有一點:參數(shù)名和變量名同名晚唇,參數(shù)優(yōu)先級高于變量提升

因為參數(shù)變量提升優(yōu)先級高巫财,所以在函數(shù)被調(diào)用后,參數(shù)傳值的執(zhí)行順序是在變量賦值之前的哩陕,即var a之后平项,是 a = 10(傳參)赫舒,相當(dāng)于以下的代碼執(zhí)行順序:

function show(){
      var a
      a = 10
      console.log(a);//10    
      a = 20
      console.log(a);//20
}    
show()

第二種情況:函數(shù)沒有參數(shù),函數(shù)內(nèi)部的變量未以關(guān)鍵字 var 定義

function show(){
      a=10    // 不加var闽瓢,此處的a就變成了全局變量
      console.log(a); //10
}
show()
console.log(a); //10

注意看第2行的a接癌,它前面沒有 var 關(guān)鍵字,此時扣讼,當(dāng)show函數(shù)被調(diào)用后缺猛,a就被添加到了window對象中,成為了一個全局變量椭符,全局變量在script的任何地方都能被訪問荔燎,所以最后一行,在函數(shù)外部也能訪問 a销钝,結(jié)果打印10(如果前面沒有調(diào)用show有咨,即show(),那么a就沒被創(chuàng)建蒸健,即未定義)

第三種情況:函數(shù) 有/無 參數(shù)座享,函數(shù)內(nèi)部的變量以 var 定義
此時的var 后面的變量就是一個局部變量,也就是說似忧,這個變量只能在其作用于內(nèi)部被訪問征讲。

function show(){
    var a=10
    console.log(a); //10
}
show()
console.log(a);// a is not defined 局部變量 不能在外邊被訪問

第四種情況:函數(shù)外部的全局變量跟函數(shù)內(nèi)部的局部變量同名

var tt = 'aa';
function test(){
    alert(tt);  //先變量提升,tt在全局和函數(shù)內(nèi)部都有橡娄,優(yōu)先考慮局部變量提升诗箍,所以var tt提到alert上面,即undefined
    var tt = 'dd';  //局部變量賦值挽唉,所以tt現(xiàn)在有值了滤祖,為"dd""
    alert(tt);  //彈出dd
}
test();

當(dāng)局部變量和全局變量都有提升時,優(yōu)先考慮局部變量提升瓶籽。

第五種情況:函數(shù)提升跟變量提升的變量重名

函數(shù)也是一個變量匠童,可以用函數(shù)聲明的方式定義,也可以用函數(shù)表達式的方式定義塑顺,所以也存在函數(shù)提升汤求。

當(dāng)有多個同名變量聲明的時候,函數(shù)聲明會覆蓋其他的聲明严拒。如果有多個函數(shù)聲明扬绪,則是由最后的一個函數(shù)聲明覆蓋之前所有的聲明。

舉個例子來解釋一下:

fn()

function fn() {
  console.log('1')
  var fn = 40
  console.log(fn)
}

function fn() {
  console.log('2')  //2
  var fn = 10
  console.log(fn) //10
}
var fn = function(){
  console.log('3')
}
console.log(fn) //function(){console.log('3')}

在這里裤唠,第一行就先調(diào)用了函數(shù)fn挤牛。因為出現(xiàn)變量重名的情況時,函數(shù)聲明高于所有變量聲明种蘸,即函數(shù)聲明最先實現(xiàn)墓赴,那么第3行和第9行的function fn就最先被聲明竞膳,又因為如果有多個函數(shù)聲明,則是由最后的一個函數(shù)聲明覆蓋之前所有的聲明诫硕,所以第9行的fn會覆蓋第3行的fn坦辟,相當(dāng)于fn這個函數(shù)的函數(shù)主題就是第9行下邊的內(nèi)容。緊接著就是fn被調(diào)用(第一行)章办,依次執(zhí)行锉走,輸出結(jié)果打印2,10(局部變量)纲菌。然后執(zhí)行到第14行的時候,因為變量提升疮绷,var fn 已經(jīng)提到頂部去了翰舌,所以這里只剩下賦值語句 fn = function{console.log('3')},相當(dāng)于給fn賦了一個新的值冬骚,就跟 var a = 1椅贱; a = 5 是一個道理。此時打印fn只冻,則輸出的是這個新的函數(shù)內(nèi)容 function{console.log('3')}庇麦。那么,如果在這后面再調(diào)用一次fn喜德,會輸出什么呢山橄?結(jié)果是3。因為此時fn就是一個新的函數(shù)了舍悯,他的主體部分就是打印字符3航棱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市萌衬,隨后出現(xiàn)的幾起案子饮醇,更是在濱河造成了極大的恐慌,老刑警劉巖秕豫,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件朴艰,死亡現(xiàn)場離奇詭異,居然都是意外死亡混移,警方通過查閱死者的電腦和手機祠墅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來歌径,“玉大人饵隙,你說我怎么就攤上這事【诓保” “怎么了金矛?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵芯急,是天一觀的道長。 經(jīng)常有香客問我驶俊,道長娶耍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任饼酿,我火速辦了婚禮榕酒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘故俐。我一直安慰自己想鹰,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布药版。 她就那樣靜靜地躺著辑舷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪槽片。 梳的紋絲不亂的頭發(fā)上何缓,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機與錄音还栓,去河邊找鬼碌廓。 笑死,一個胖子當(dāng)著我的面吹牛剩盒,可吹牛的內(nèi)容都是我干的谷婆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼辽聊,長吁一口氣:“原來是場噩夢啊……” “哼波材!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起身隐,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤廷区,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后贾铝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體隙轻,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年垢揩,在試婚紗的時候發(fā)現(xiàn)自己被綠了玖绿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡叁巨,死狀恐怖斑匪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情锋勺,我是刑警寧澤蚀瘸,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布狡蝶,位于F島的核電站,受9級特大地震影響贮勃,放射性物質(zhì)發(fā)生泄漏贪惹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一寂嘉、第九天 我趴在偏房一處隱蔽的房頂上張望奏瞬。 院中可真熱鬧,春花似錦泉孩、人聲如沸硼端。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽珍昨。三九已至,卻和暖如春订咸,著一層夾襖步出監(jiān)牢的瞬間曼尊,已是汗流浹背酬诀。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工脏嚷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瞒御。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓父叙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親肴裙。 傳聞我的和親對象是個殘疾皇子趾唱,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,828評論 2 345

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

  • 1. 什么是變量提升? 當(dāng)棧內(nèi)存(作用域)形成蜻懦, JS代碼自上而下執(zhí)行之前甜癞,瀏覽器首先會把所有帶var/funct...
    _hider閱讀 2,910評論 0 2
  • 像變量提升和函數(shù)提升這種偏學(xué)院派的問題在面試中出現(xiàn)的概率很高,在實際開發(fā)中也會影響到編程的效率宛乃。 前段時間在網(wǎng)上做...
    時和歲稔閱讀 1,047評論 1 7
  • 1.提升的概念 簡單說就是在js代碼執(zhí)行前引擎會先進行預(yù)編譯悠咱,預(yù)編譯期間會將變量聲明與函數(shù)聲明提升至其對應(yīng)作用域的...
    dream_Q閱讀 445評論 0 0
  • 概念 從概念的字面意義上說,“變量提升”意味著變量和函數(shù)的聲明會在物理層面移動到代碼的最前面征炼,但這么說并不準確析既。實...
    Mokingc閱讀 170評論 0 0
  • 沒錯,經(jīng)典變量提升谆奥,經(jīng)典炒冷飯眼坏,我將其稱之為典中典。 什么是提升酸些? 引擎會在解釋 JavaScript 代碼之前首...
    AmingYo閱讀 193評論 0 0