變量提升
網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、微信小程序定制開(kāi)發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了南沙免費(fèi)建站歡迎大家使用!
JavaScript的變量提升有兩種,用var聲明的變量以及用function聲明的變量。
用var聲明的變量
我們先來(lái)看下面這段代碼,a的值是多少
代碼1
console.log(a); var a;
按照以往編程語(yǔ)言的思路來(lái)看,代碼自上而下運(yùn)行,按這種思路,會(huì)報(bào)錯(cuò),因?yàn)閳?zhí)行到第2行時(shí),變量a還沒(méi)有定義,所以會(huì)報(bào)錯(cuò)a is not defined
然而事實(shí)上答案是undefined
好,抱著疑惑,我們看下面的代碼
var a; console.log(a);
我們發(fā)現(xiàn),這兩段代碼是一樣的,那么又有一個(gè)新的問(wèn)題,是不是有沒(méi)有var a都無(wú)所謂,它的答案始終是undefined,才造成了以為變量會(huì)提升的錯(cuò)覺(jué),于是我寫了代碼3
代碼3
console.log(a);
好,它終于報(bào)錯(cuò)了,所以這證明了javaScript代碼并不是自上而下執(zhí)行的,至少?gòu)谋砻婵瓷厦媸沁@樣的。
于是我們?cè)倏创a4
代碼4
console.log(a); var a = 2;
因?yàn)樽兞刻嵘铮源鸢甘?,然而事實(shí)上,它依然是undefined,why?
這時(shí)候我們有請(qǐng)編譯器這位負(fù)責(zé)語(yǔ)法分析及代碼生成等臟活累活的大佬。
編譯器在看到var a = 2;,它會(huì)將其看做兩個(gè)聲明,var a;和a = 2,第一個(gè)聲明在編譯階段進(jìn)行,第二個(gè)聲明會(huì)被原地等待執(zhí)行階段。
也就是說(shuō)上面代碼,會(huì)變成下面的這段代碼
var a; console.log(a); a = 2;
所以最終會(huì)是undefined
好,我在啰嗦一下,看這段代碼5
代碼5
a = 2; var a; console.log(a);
我想大家應(yīng)該已經(jīng)知道這段代碼執(zhí)行時(shí)的真正順序及其答案了,沒(méi)錯(cuò),答案是2,但我想說(shuō)的是把第2行給注釋掉,答案依然是2,但這個(gè)和變量提升沒(méi)啥關(guān)系了,是嚴(yán)格模式與非嚴(yán)格模式的鍋,在非嚴(yán)格模式下允許開(kāi)發(fā)者可以不使用聲明變量的關(guān)鍵字,但在嚴(yán)格模式下是不可以的,它會(huì)報(bào)錯(cuò)的。
用function聲明的變量
與var一樣,function聲明的變量依然會(huì)提升。
log(5); function log(mes){ console.log(mes) }
按照之前的變量提升的理解,這段代碼的真正順序是這樣的,
function log(mes){ console.log(mes) } log(5);
很好,很正確,那么再看下一段代碼
log(5); var log = function(mes){ console.log(mes) }
它報(bào)錯(cuò)了,log is not a function,從這里我們可以看出,這種函數(shù)表達(dá)式是不會(huì)被提升的,只有函數(shù)聲明才會(huì)被提升,試著在最前面新增一行代碼console.log(log),會(huì)先輸出undefined。
所以這里的真正順序是
var log; log(); //這時(shí)候只是聲明了log這個(gè)變量,并不是函數(shù),卻用函數(shù)的方法調(diào)用它,所以會(huì)報(bào)錯(cuò),說(shuō)這不是一個(gè)函數(shù)。 log = function(mes){ console.log(mes) }
在function里用var聲明變量
我們雖然知道,var聲明的變量會(huì)提升,但并不知道會(huì)提升到哪個(gè)程度。
在此之前來(lái)看一段代碼
var a = 4; function foo(){ var a = 5; console.log(a); } foo(); console.log(a)
答案是5,4,先輸出5,再輸出4。
用var聲明的變量是有函數(shù)作用域的,所以foo里的a和foo外面的a沒(méi)有任何關(guān)系,這種情況正是我想要的。
再改下代碼
function foo(){ a = 5 console.log(a); var a; } foo(); console.log(a)
答案是5,a is not defined
第4行代碼輸出5,第9行報(bào)錯(cuò)。
這種情況就是變量提升只會(huì)提升到變量所在的 作用域的頂部,不會(huì)提升到父級(jí)作用域。
因此可以得出一個(gè)結(jié)論:變量提升只會(huì)將變量提升到自己所在的作用域的頂部
函數(shù)優(yōu)先
既然用var和function的變量都有提升的功能,那如果同一個(gè)變量用這兩種都聲明會(huì)怎樣,好吧,看標(biāo)題就知道了,函數(shù)優(yōu)先。
具體看下代碼
foo(); var foo; function foo(){ console.log(1) } foo = function(){ console.log(2) }
答案是1
這段代碼其實(shí)這樣子的
function foo(){ console.log(1) } foo();// 1 foo = function(){ console.log(2) }
仔細(xì)一看,var foo;沒(méi)了,沒(méi)錯(cuò),它被引擎忽略了,認(rèn)為重復(fù)聲明所以把它拋棄了。
好,既然var聲明的變量比不了函數(shù)聲明,那就用函數(shù)聲明,多次聲明同個(gè)變量。
foo() function foo(){ console.log(1); } foo() function foo(){ console.log(2); } foo() function foo(){ console.log(3); } foo()
foo聲明了三次,調(diào)用了四次,每次調(diào)用的結(jié)果都是3,所以最后的函數(shù)聲明會(huì)覆蓋之前的函數(shù)聲明
但是var還想掙扎一下,覺(jué)得還是有必要證明自己的存在感的。
foo() function foo(){ console.log(1); } var foo; foo() foo = function(){ console.log(2); } foo() function foo(){ console.log(3); } foo()
仔細(xì)看,中間那部分代碼改了,依次輸出3,3,2,2
雖然var foo被忽略了,但下面的函數(shù)還是有用的,這段代碼可以看成是這樣的
function foo(){ console.log(3); } foo();//3 foo();//3 foo = function(){ console.log(2); } foo();//2 foo();//2
在普通塊內(nèi)部聲明函數(shù)
之前是在作用域聲明函數(shù),現(xiàn)在來(lái)塊里面聲明函數(shù)
function foo(){ console.log(b); // undefined b(); //TypeError: b is not a function var a = true; if(a){ function b(){ console.log(2) } //下面這段代碼和上面的結(jié)果一樣 // var b = function(){ // console.log(2) // } } //b() --> 這里會(huì)被執(zhí)行 } foo()
從上面看上去,b是undefined,證明這個(gè)變量還是有的,只不過(guò)它并不是一個(gè)函數(shù),這情況和用函數(shù)表達(dá)式差不多。
總結(jié)
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)創(chuàng)新互聯(lián)的支持。