更新時(shí)間:2020-08-05 來源:黑馬程序員 瀏覽量:
JavaScript是解釋型的語言,但是他并不是真的在運(yùn)行的時(shí)候逐句的往下解析執(zhí)行。
我們來看下面這個(gè)例子:
在上面這段代碼中,函數(shù)func的調(diào)用是在其聲明之前,如果說JavaScript代碼真的是逐句的解析執(zhí)行,那么在第一句調(diào)用的時(shí)候就會(huì)出錯(cuò),然而事實(shí)并非如此,上面的代碼可以正常執(zhí)行,并且alert出來`Function has been called`。
所以,可以得出結(jié)論,JavaScript并非僅在運(yùn)行時(shí)簡(jiǎn)簡(jiǎn)單單的逐句解析執(zhí)行!
JavaScript引擎在對(duì)JavaScript代碼進(jìn)行解釋執(zhí)行之前,會(huì)對(duì)JavaScript代碼進(jìn)行預(yù)解析,在預(yù)解析階段,會(huì)將以關(guān)鍵字`var`和`function`開頭的語句塊提前進(jìn)行處理。
關(guān)鍵問題是怎么處理呢?
當(dāng)變量和函數(shù)的聲明處在作用域比較靠后的位置的時(shí)候,變量和函數(shù)的聲明會(huì)被提升到作用域的開頭。
重新來看上面的那段代碼
由于JavaScript的預(yù)解析機(jī)制,上面的代碼就等效于:
看完函數(shù)聲明的提升,再來看一個(gè)變量聲明提升的例子:
由于JavaScript的預(yù)解析機(jī)制,上面這段代碼,alert出來的值是undefined,如果沒有預(yù)解析,代碼應(yīng)該會(huì)直接報(bào)錯(cuò)a is not defined,而不是輸出值。
Wait a minute, 不是說要提前的嗎?那不是應(yīng)該alert出來1,為什么是undefined?
那么在這里有必要說一下聲明、定義、初始化的區(qū)別。其實(shí)這幾個(gè)概念是C系語言的人應(yīng)該都比較了解的。
所以我們說的提升,是聲明的提升。
那么再回過頭看,上面的代碼就等效于:
通過上一小節(jié)的內(nèi)容,我們對(duì)變量、函數(shù)聲明提升已經(jīng)有了一個(gè)最基本的理解。那么接下來,我們就來分析一些略復(fù)雜的情況。
觀察下面這段代碼:
輸出結(jié)果為:
原因分析:由于預(yù)解析機(jī)制,func1的聲明會(huì)被提升,提升之后的代碼為:
同名的函數(shù),后面的會(huì)覆蓋前面的,所以兩次輸出結(jié)果都是`This is last func1`。
當(dāng)出現(xiàn)變量聲明和函數(shù)同名的時(shí)候,只會(huì)對(duì)函數(shù)聲明進(jìn)行提升,變量會(huì)被忽略。所以上面的代碼的輸出結(jié)果為
我們還是來吧預(yù)解析之后的代碼展現(xiàn)出來:
再來看一種
代碼執(zhí)行結(jié)果為:
直接上預(yù)解析后的代碼:
聲明提升并不是將所有的聲明都提升到window對(duì)象下面,提升原則是提升到變量運(yùn)行的環(huán)境(作用域)中去。
還是直接把預(yù)解析之后的代碼寫出來:
分段,其實(shí)就分script標(biāo)簽的
在上面代碼中,第一個(gè)script標(biāo)簽中的兩個(gè)`func`進(jìn)行了提升,第二個(gè)`func`覆蓋了第一個(gè)`func`,但是第二個(gè)script標(biāo)簽中的`func`并沒有覆蓋上面的第二個(gè)`func`。所以說預(yù)解析是分段的。
tip:但是要注意,分段只是單純的針對(duì)函數(shù),變量并不會(huì)分段預(yù)解析。
這里會(huì)直接報(bào)錯(cuò),`func is not a function`,原因就是函數(shù)表達(dá)式,并不會(huì)被提升。只是簡(jiǎn)單地當(dāng)做變量聲明進(jìn)行了處理,如下:
上面這段代碼,就是所謂的條件式函數(shù)聲明,這段代碼在Gecko引擎中打印`"undefined"`、`"function"`;而在其他瀏覽器中則打印`"function"`、`"function"`。
原因在于Gecko加入了ECMAScript以外的一個(gè)feature:條件式函數(shù)聲明。
Conditionally created functions Functions can be conditionally declared, that is, a function declaration can be nested within an if statement.
Note: Although this kind of function looks like a function declaration, it is actually an expression (or statement), since it is nested within another statement. See differences between function declarations and function expressions.
Note中的文字說明,條件式函數(shù)聲明的處理和函數(shù)表達(dá)式的處理方式一樣,所以條件式函數(shù)聲明沒有聲明提升的特性。
猜你喜歡: