js變量提升與編譯原理

?在文章開始之前附上之前一段代碼,它會(huì)輸出什么呢?

fn()
console.log(a)
a = 2
console.log(a)
var a = 3
console.log(a)


function fn() {
    console.log(a)
    var a = 4
    console.log(a)
}


?眾所周知js屬于解釋型語言,它是執(zhí)行的時(shí)候才會(huì)編譯,是可以在解釋器中直接執(zhí)行的語言,不需要編譯;js在執(zhí)行時(shí)分為三個(gè)階段,語法檢測,預(yù)編譯和解釋執(zhí)行。

  • 語法檢測階段:檢查代碼有無語法錯(cuò)誤
  • 預(yù)編譯階段:創(chuàng)建上下文對(duì)象,var聲明的變量作為上下文屬性,用undefined進(jìn)行初始化,function聲明的函數(shù)也作為上下文對(duì)象,但是是保持了定義內(nèi)容的。另外,function聲明的優(yōu)先級(jí)是高于var的。這就是var和function的變量提升
  • 解釋執(zhí)行:在解釋執(zhí)行過程中,變量在解析時(shí)先按照上下文對(duì)象尋找,如果沒有則按照上下文對(duì)象的原型鏈尋找,還尋找不到就會(huì)去上級(jí)作用域?qū)ふ摇?/li>

學(xué)了這個(gè)編譯原理,上面的代碼就很簡單了

fn()                                // function聲明的函數(shù)最優(yōu)先 輸出undefined  4
console.log(a)             // var變量提升 輸出undefined
a = 2                          
console.log(a)              // 輸出 2
var a = 3    
console.log(a)             // 輸出 3


function fn() {     
    console.log(a)         // var變量提升,a優(yōu)先在本上下文對(duì)象中尋找,故輸出undefined
    var a = 4                // 變量提升
    console.log(a)       // 變量賦值  輸出4
}
// 輸出順序?yàn)閡ndefined 4 undefined 2 3
b()  // function 變量提升所以輸出22
var b = function () {
    console.log(11)
}
b()  // b被賦值所以輸出11
function b() {
    console.log(22)
}
b() // function被提升所以輸出11

下面是一些關(guān)于變量提升相關(guān)的面試題

例 1:var 聲明的變量提升的問題,var 聲明的變量會(huì)提升到作用域最頂部,而賦值會(huì)保留在原位,所以 a 是 undefined;因?yàn)?let,const 沒有變量提升,所以打印 b 會(huì)報(bào)錯(cuò)無法在初始化之前訪問 b

/* var聲明變量提升的問題 */

console.log(a)  // undefined
var a = 12
console.log(a)  // 12

console.log(b); // Error:Cannot access 'b' before initialization
let b = 13;

例 2: var 變量提升,且不會(huì)形成塊級(jí)作用域,所以 var 聲明會(huì)提升到 fn 函數(shù)的最頂部,故 a 為 undefined,因?yàn)?a 為 undefined,所以不會(huì)進(jìn)入 if 里面,故打印為 undefined

function fn(){
    if(a){
        var a = 100
    }
    console.log(a)  // undefined
}

fn()

例 3:在 fn 函數(shù)內(nèi) var 變量提升,所以 a=undefined,進(jìn)入 if 內(nèi)部賦值 a=4

var a = 100
function fn(){
    if(a === undefined){
        var a = 4
    }
    console.log(a) // 4
}
fn()

例 4:function 聲明會(huì)整個(gè)提升,而且優(yōu)先級(jí)比 var 申明高,所以后面 fn=test 會(huì)把函數(shù)聲明給覆蓋掉

var fn = 'test'
function fn(){
    console.log('ss')
}
console.log(fn) // test
fn() // Error: fn is not a function

例 5:function 變量提升,后面被 fn 賦值覆蓋

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

function fn(){
    console.log(2)
}

fn() // log 1

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容