javascript
JS----预编译及变量提升详解
前言
JS屬于解釋型語(yǔ)言,在執(zhí)行過(guò)程中順序執(zhí)行,但是會(huì)分塊先預(yù)編譯然后才執(zhí)行。因此在JS中存在一種變量提升的現(xiàn)象。搞懂預(yù)編譯環(huán)節(jié),變量提升自然而然也就懂了。本文講圍繞以下幾點(diǎn)進(jìn)行介紹(變量提升會(huì)穿插在其中講解):
- 預(yù)編譯執(zhí)行步驟
- 示例演示
預(yù)編譯執(zhí)行步驟
預(yù)編譯發(fā)生在函數(shù)執(zhí)行的前一刻,過(guò)程如下:
至此,預(yù)編譯環(huán)節(jié)結(jié)束,函數(shù)中咯變量按照最終AO對(duì)象中的值開(kāi)始執(zhí)行。接下來(lái),結(jié)合示例演示就會(huì)更加清晰。
示例演示
我們先來(lái)看下面這段代碼:
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); 復(fù)制代碼接下來(lái)我們來(lái)按照前面的步驟詳細(xì)分析它的預(yù)編譯執(zhí)行過(guò)程:
預(yù)編譯環(huán)節(jié)就此結(jié)束,此時(shí)的AO對(duì)象已經(jīng)更新為:
AO{a : function a(){},b : undefined,d : function d(){} } 復(fù)制代碼函數(shù)開(kāi)始逐行順序執(zhí)行:
function fn(a){console.log(a);// 輸出functiona(){}var a = 123;//執(zhí)行到這里重新對(duì)a賦,AO對(duì)象再一次更新console.log(a);// 輸出123function a(){};//預(yù)編譯環(huán)節(jié)已經(jīng)進(jìn)行了變量提升,故執(zhí)行時(shí)不在看這行代碼console.log(a);// 輸出123var b = function(){};//這個(gè)是函數(shù)表達(dá)式不是函數(shù)聲明,故不能提升,會(huì)對(duì)AO中的b重新賦值console.log(b);//輸出function(){}function d(){};} 復(fù)制代碼至此,函數(shù)執(zhí)行完畢,銷毀AO對(duì)象。
我們?cè)賮?lái)看幾個(gè)例子,熟悉函數(shù)的預(yù)編譯過(guò)程。
示例一:
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); 復(fù)制代碼它的AO創(chuàng)建過(guò)程如下(此處省略創(chuàng)建空AO對(duì)象的部分,下文同):
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(){} } 復(fù)制代碼至此預(yù)編譯環(huán)節(jié)完成,開(kāi)始執(zhí)行:
function test (a,b){console.log(a); //輸出1c = 0; //給AO對(duì)象中的c重新賦值0var c;//預(yù)編譯環(huán)節(jié)變量提升,不再讀此行代碼a = 3;//給AO對(duì)象中的a重新賦值3b = 2;//給AO對(duì)象中的b重新賦值2console.log(b);//輸出2function b(){};//預(yù)編譯環(huán)節(jié)變量提升,執(zhí)行時(shí)不再讀這行代碼function d(){};//預(yù)編譯環(huán)節(jié)變量提升,執(zhí)行時(shí)不再讀這行代碼console.log(b);//輸出2 } //調(diào)用函數(shù) test(1); 復(fù)制代碼示例二:
這個(gè)例子中我們引入全局對(duì)象GO。GO與AO的過(guò)程類似
function test(){var a = b = 123; } test(); 復(fù)制代碼此函數(shù)的執(zhí)行過(guò)程:先把123賦給b,再聲明a,再把b賦給a。此時(shí)變量b未經(jīng)聲明就賦值,為全局變量。預(yù)編譯環(huán)節(jié)如下:
GO1{b : undefined } AO1{a : undefined }GO2{b : 123; } AO2{a : 123; } 復(fù)制代碼示例三 :
console.log(test); function test(test){console.log(test);var test = 234;console.log(test);function test(){}; } test(1); var test = 123; 復(fù)制代碼我們來(lái)看它的預(yù)編譯過(guò)程:
//執(zhí)行前(頁(yè)面加載完成時(shí))生成GO對(duì)象 GO1{test : undefined } GO2{test : function(){} }//輸出 function test(){...}//執(zhí)行test()前生成它的AO對(duì)象 AO1{test : undefined } AO2{test : 1 } AO3{test : function test(){} }//預(yù)編譯結(jié)束開(kāi)始執(zhí)行test(1); AO4{test : 234 } //輸出234 復(fù)制代碼示例四:
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); 復(fù)制代碼我們來(lái)看它的預(yù)編譯過(guò)程:
//首先是全局對(duì)象GO GO1{a : undefined } G02{a : undefined,demo : function demo(){} } //執(zhí)行demo()前預(yù)編譯,由于demo中的c未聲明就使用故為全局對(duì)象//輸出undefined GO3{a : undefined,demo : function demo(){}c : undefined } //此時(shí)a還是undefined,故不執(zhí)行if()代碼塊 //輸出還是undefined GO4{a : undefined,demo : function demo(){}c : 234; } //輸出234 GO5{a : 10,demo : function demo(){}c : 234; } //輸出234 復(fù)制代碼總結(jié)
以上是生活随笔為你收集整理的JS----预编译及变量提升详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 每日优鲜生鲜超市(每日英语听力)
- 下一篇: Spring框架中的Quartz定时任务