? ? ? ? ?javascript運(yùn)行機(jī)制之執(zhí)行順序詳解
JavaScript是一種描述型腳本語(yǔ)言,它不同于java或C#等編譯性語(yǔ)言,它不需要進(jìn)行編譯成中間語(yǔ)言,而是由瀏覽器進(jìn)行動(dòng)態(tài)地解析與執(zhí)行。如果你不能理解javaScript語(yǔ)言的運(yùn)行機(jī)制,或者簡(jiǎn)單地說(shuō)迁霎,你不能掌握javascript的執(zhí)行順序祷肯,那你就猶如伯樂(lè)駕馭不了千里馬,讓千里馬脫韁而出有鹿,四處亂竄鼓黔。
那么JavaScript是怎么來(lái)進(jìn)行解析的嗎央勒?它的執(zhí)行順序又是如何的呢?在了解這些之前请祖,我們先來(lái)認(rèn)識(shí)幾個(gè)重要的術(shù)語(yǔ):
1订歪、代碼塊
JavaScript中的代碼塊是指由標(biāo)簽分割的代碼段脖祈。例如:
JS是按照代碼塊來(lái)進(jìn)行編譯和執(zhí)行的肆捕,代碼塊間相互獨(dú)立,但變量和方法共享盖高。什么意思呢? 舉個(gè)例子慎陵,你就明白了:
上面的代碼中代碼塊一中運(yùn)行報(bào)錯(cuò)眼虱,但不影響代碼塊二的執(zhí)行,這就是代碼塊間的獨(dú)立性席纽,而代碼塊二中能調(diào)用到代碼一中的變量捏悬,則是塊間共享性。
2润梯、聲明式函數(shù)與賦值式函數(shù)
JS中的函數(shù)定義分為兩種:聲明式函數(shù)與賦值式函數(shù)过牙。代碼塊中,而需要在頁(yè)面元素加載完后的js放在元素后面纺铭,body標(biāo)簽的onload事件是在最后執(zhí)行的寇钉。
聲明式函數(shù)與賦值式函數(shù)的區(qū)別在于:在JS的預(yù)編譯期,聲明式函數(shù)將會(huì)先被提取出來(lái)舶赔,然后才按順序執(zhí)行js代碼扫倡。
3、預(yù)編譯期與執(zhí)行期
事實(shí)上竟纳,JS的解析過(guò)程分為兩個(gè)階段:預(yù)編譯期(預(yù)處理)與執(zhí)行期撵溃。
預(yù)編譯期JS會(huì)對(duì)本代碼塊中的所有聲明的變量和函數(shù)進(jìn)行處理(類似與C語(yǔ)言的編譯),但需要注意的是此時(shí)處理函數(shù)的只是聲明式函數(shù)锥累,而且變量也只是進(jìn)行了聲明但未進(jìn)行初始化以及賦值缘挑。
理解了上面的幾個(gè)術(shù)語(yǔ),相信大家對(duì)JS的運(yùn)行機(jī)制已經(jīng)有了個(gè)大概的印象了揩悄,現(xiàn)在我們來(lái)看個(gè)例子:
為什么運(yùn)行上面的代碼瀏覽器會(huì)報(bào)錯(cuò)呢卖哎?聲明函數(shù)不是會(huì)在預(yù)處理期就會(huì)被處理了嗎,怎么還會(huì)找不到Fn()函數(shù)呢删性?其實(shí)這是一個(gè)理解誤點(diǎn)亏娜,我們上面說(shuō)了JS引擎是按照代碼塊來(lái)順序執(zhí)行的,其實(shí)完整的說(shuō)應(yīng)該是按照代碼塊來(lái)進(jìn)行預(yù)處理和執(zhí)行的蹬挺,也就是說(shuō)預(yù)處理的只是執(zhí)行到的代碼塊的聲明函數(shù)和變量维贺,而對(duì)于還未加載的代碼塊,是沒(méi)法進(jìn)行預(yù)處理的巴帮,這也是邊編譯邊處理的核心所在溯泣。
代碼塊中,而需要在頁(yè)面元素加載完后的js放在元素后面榕茧,body標(biāo)簽的onload事件是在最后執(zhí)行的垃沦。