JS----預編譯及變量提升詳解

2019-11-18    seo達人

JS----預編譯及變量提升詳解

JS屬于解釋型語言,在執(zhí)行過程中順序執(zhí)行,但是會分塊先預編譯然后才執(zhí)行。因此在JS中存在一種變量提升的現(xiàn)象。搞懂預編譯環(huán)節(jié),變量提升自然而然也就懂了。本文講圍繞以下幾點進行介紹(變量提升會穿插在其中講解):



預編譯執(zhí)行步驟

示例演示



預編譯執(zhí)行步驟

預編譯發(fā)生在函數(shù)執(zhí)行的前一刻,過程如下:



創(chuàng)建AO對象,執(zhí)行期上下文(后面更新關于執(zhí)行期上下文詳解)。

尋找函數(shù)的形參和變量聲明,將變量和形參名作為AO對象的屬性名,值設定為undefined.

將形參和實參相統(tǒng)一,即更改形參后的undefined為具體的形參值。

尋找函數(shù)中的函數(shù)聲明,將函數(shù)名作為AO屬性名,值為函數(shù)體。



至此,預編譯環(huán)節(jié)結(jié)束,函數(shù)中咯變量按照最終AO對象中的值開始執(zhí)行。接下來,結(jié)合示例演示就會更加清晰。



作者:北海北方

鏈接:https://juejin.im/post/5aa6693df265da23884cb571

來源:掘金

著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。



示例演示

我們先來看下面這段代碼:

function fn(a){

console.log(a);

var a = 123;

console.log(a);



    function a(){};

    console.log(a);

    

    var b = function(){};

    console.log(b);

    

    function d(){};

 }

 

 //調(diào)用函數(shù)

 fn(1);



作者:北海北方

鏈接:https://juejin.im/post/5aa6693df265da23884cb571

來源:掘金

著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

接下來我們來按照前面的步驟詳細分析它的預編譯執(zhí)行過程:



創(chuàng)建AO對象



AO{

    //空對象    

}

復制代碼

找形參和變量聲明



AO{

    a : undefined,

    b : undefined

}

復制代碼

形參和實參相統(tǒng)一



AO{

    a : 1,

    b : undefined

}

復制代碼

找函數(shù)聲明



AO{

    a : function a(){},

    b : undefined,

    d : function d(){}

}

復制代碼預編譯環(huán)節(jié)就此結(jié)束,此時的AO對象已經(jīng)更新為:

AO{

    a : function a(){},

    b : undefined,

    d : function d(){}

}

復制代碼函數(shù)開始逐行順序執(zhí)行:

 function fn(a){

    console.log(a);// 輸出functiona(){}

    var a = 123;//執(zhí)行到這里重新對a賦,AO對象再一次更新

    console.log(a);// 輸出123

    

    function a(){};//預編譯環(huán)節(jié)已經(jīng)進行了變量提升,故執(zhí)行時不在看這行代碼

    console.log(a);// 輸出123

    

    var b = function(){};//這個是函數(shù)表達式不是函數(shù)聲明,故不能提升,會對AO中的b重新賦值

    console.log(b);//輸出function(){}

    

    function d(){};

 }

復制代碼至此,函數(shù)執(zhí)行完畢,銷毀AO對象。

我們再來看幾個例子,熟悉函數(shù)的預編譯過程。

示例一:

function test (a,b){

    console.log(a);

    c = 0;

    var c;

    a = 3;

    b = 2;

    console.log(b);

    function b(){};

    function d(){};

    console.log(b);



//調(diào)用函數(shù)

test(1);

復制代碼它的AO創(chuàng)建過程如下(此處省略創(chuàng)建空AO對象的部分,下文同):

AO1{

    a : undefined,

    b : undefined,

    c : undefined

}



AO2{

    a : 1,

    b : undefined,

    c : undefined

}



AO3{

    a : 1,

    b : function b(){},

    c : undefined,

    d : function d(){}

}

復制代碼至此預編譯環(huán)節(jié)完成,開始執(zhí)行:

function test (a,b){

    console.log(a); //輸出1

    c = 0; //給AO對象中的c重新賦值0

    var c;//預編譯環(huán)節(jié)變量提升,不再讀此行代碼

    a = 3;//給AO對象中的a重新賦值3

    b = 2;//給AO對象中的b重新賦值2

    console.log(b);//輸出2

    function b(){};//預編譯環(huán)節(jié)變量提升,執(zhí)行時不再讀這行代碼

    function d(){};//預編譯環(huán)節(jié)變量提升,執(zhí)行時不再讀這行代碼

    console.log(b);//輸出2



//調(diào)用函數(shù)

test(1);



復制代碼示例二:

這個例子中我們引入全局對象GO。GO與AO的過程類似

function test(){

var a = b = 123;

}

test();

復制代碼此函數(shù)的執(zhí)行過程:先把123賦給b,再聲明a,再把b賦給a。此時變量b未經(jīng)聲明就賦值,為全局變量。預編譯環(huán)節(jié)如下:

GO1{

b : undefined

}

AO1{

a : undefined

}



GO2{

    b : 123;

}

AO2{

    a : 123;

}

復制代碼示例三 :

console.log(test);

function test(test){

   console.log(test);

   var test = 234;

   console.log(test);

   function test(){};

}

test(1);

var test = 123;

復制代碼我們來看它的預編譯過程:

//執(zhí)行前(頁面加載完成時)生成GO對象

GO1{

    test : undefined

}

GO2{

    test : function(){}

}



//輸出 function test(){...}



//執(zhí)行test()前生成它的AO對象

AO1{

    test : undefined

}

AO2{

    test : 1

}

AO3{

    test : function test(){}

}



//預編譯結(jié)束開始執(zhí)行test(1);

AO4{

    test : 234

}

//輸出234

復制代碼示例四:

function demo(){

    console.log(b);

    if(a){

        var b = 100;

    }

    console.log(b);

    c = 234;

    console.log(c);

}

var a;

demo();

a = 10;

console.log(c);

復制代碼我們來看它的預編譯過程:

//首先是全局對象GO 

GO1{

    a : undefined

}

G02{

    a : undefined,

    demo : function demo(){}

}

//執(zhí)行demo()前預編譯,由于demo中的c未聲明就使用故為全局對象



//輸出undefined

GO3{

    a : undefined,

    demo : function demo(){}

    c : undefined

}

//此時a還是undefined,故不執(zhí)行if()代碼塊

//輸出還是undefined

GO4{

    a : undefined,

    demo : function demo(){}

    c : 234;

}

//輸出234

GO5{

    a : 10,

    demo : function demo(){}

    c : 234;

}

//輸出234


分享本文至:

日歷

鏈接

個人資料

藍藍設計的小編 http://bouu.cn

存檔