如果一個文檔流中包含多個script代碼段(用script標(biāo)簽分隔的js代碼或引入的js文件),運行順序是:
step1. 讀入第一個代碼段,JavaScript執(zhí)行引擎并非一行一行地執(zhí)行程序,而是一段一段地分析執(zhí)行的(以<\script\>標(biāo)簽來分割)
step2. 做語法分析,有錯則報語法錯誤(比如括號不匹配等),并跳轉(zhuǎn)到step5
step3. 對var變量做聲明(初始為undefined)和function定義做“預(yù)解析”(永遠(yuǎn)不會報錯的,因為只解析正確的聲明)
step4. 執(zhí)行代碼段,有錯則報錯(比如變量未定義)
step5. 如果還有下一個代碼段,則讀入下一個代碼段,重復(fù)step2
step6. 結(jié)束

JS的編譯過程:
眾所周知,javascript是解釋型語言,它不同于c#和java等編譯型語言。對于傳統(tǒng)編譯型語言來說,編譯步驟分為:詞法分析、語法分析、語義檢查、代碼優(yōu)化和字節(jié)生成;但對于解釋型語言來說,通過詞法分析和語法分析得到語法樹后,就可以開始解釋執(zhí)行了。
例子:
alert(testNum);
alert('ok');
testNum?=?2;
//testNum未聲明,執(zhí)行報錯。
alert(testNum);
alert('ok');
vartestNum?=?2;
//彈出undefined和ok。預(yù)編譯的時候,聲明了變量t;執(zhí)行到alert(t)這行代碼的時候,t尚未被賦值,所以彈出undefined。
testFunc();
functiontestFunc()?{}
alert('ok');
//彈出ok。預(yù)編譯的時候,解析了定義式函數(shù)語句function?testFunc()?{},順利執(zhí)行。
testFunc();
vartestFunc?=function()?{};
alert('ok');
//testFunc不是函數(shù),執(zhí)行報錯。預(yù)編譯的時候,聲明了變量testFunc?=?undefined;執(zhí)行到testFunc()時,testFunc還等于undefined,不是函數(shù),所以執(zhí)行testFunc()會報錯。
<\script?type="text/javascript">
testFunc();
alert('first?block');
<\script?type="text/javascript">
alert('second?block');
//彈出second?block。因為JS是一段一段執(zhí)行的,第一段執(zhí)行到testFunc()的時候報錯,整個第一段都不會再執(zhí)行,第二段正常執(zhí)行。