可能大多數人都這麼認為,JavaScript的解析與執行過程都是順序的...其實不然........
method2.js:
/** part 2 */function method2(){alert("method2~~");}
<!DOCTYPE html><html> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>JavaScript解析過程你真的清楚嗎??</title><script type="text/javascript">/** part 1 */function method1(){alert("method1~~");}</script><script type="text/javascript" src="method2.js"></script><script type="text/javascript">/** part 3 */function method3(){alert("method3~~");}method1();//alert method1~~method2();//alert method2~~method3();//alert method3~~</script> </head> <body> This is my HTML page. <br> </body></html>
我想對於這3個函數的定義,以及最後的調用的結果,大部分人是沒有疑問的。那麼.....
Test 1:
<!DOCTYPE html><html> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>JavaScript解析過程你真的清楚嗎??</title><script type="text/javascript">/** part 1 */function method1(){alert("method1~~");}</script><script type="text/javascript" src="method2.js"></script><script type="text/javascript">/** part 3 *///注意:這是在method3函數定義的上面調用method1();method2();method3();function method3(){alert("method3~~");}</script> </head> <body> This is my HTML page. <br> </body></html>
當我把method1();method2();method3()的調用代碼寫在了method3函數的定義之上的時候呢???
我想大部分人對於method1();method2();的執行結果是沒有疑問的。彈出method1~~ method2~~ 如果有疑問...你就得面壁去了^_^
method3();的執行結果呢?認為報錯的童鞋,你就有必要仔細看了哦。 其結果是彈出 method3~~
這是為什麼呢? 用犀牛書(JavaScript權威指南)第五版譯文中的一句話解釋:
"函數定義在解析時,而不再運行時"
也就是javascript引擎會先處理函數的定義,再執行方法調用(在本例中,只有方法調用);
接下來....
Test 2:
<!DOCTYPE html><html> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>JavaScript解析過程你真的清楚嗎??</title><script type="text/javascript">/** part 1 *///調用寫在了part1的script標籤內method1();method2();method3();function method1(){alert("method1~~");}</script><script type="text/javascript" src="method2.js"></script><script type="text/javascript">/** part 3 */function method3(){alert("method3~~");}</script> </head> <body> This is my HTML page. <br> </body></html>
經過Test 1的結論,相比大傢伙得出的結果應該是彈出:method1~~ method2~~ method3~~
但是....只答對了1/3,只有method1彈出,然後就報錯了...
繼續看...
Test 3:
<!DOCTYPE html><html> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>JavaScript解析過程你真的清楚嗎??</title><script type="text/javascript">//調用與方法定義不再一個script中,並且在函數定義的script的上面method1();method2();method3();</script><script type="text/javascript">/** part 1 */function method1(){alert("method1~~");}</script><script type="text/javascript" src="method2.js"></script><script type="text/javascript">/** part 3 */function method3(){alert("method3~~");}</script> </head> <body> This is my HTML page. <br> </body></html>
這次,我把調用的代碼寫在一個單獨的script標籤內,並且該script標籤,在其他script標籤之上
執行結果為:直接報錯。
alert方法想必大家都知道,它是window對象的方法(也可以稱之為window的一個屬性,只不過這個屬性是一個函數而已),調用時候可以省略window 直接寫alert(); 也可以寫成 window.alert();
經過反覆測試,結合犀牛書的那句話。筆者認為:
JavaScript引擎每次遇到script標籤時,先處理函數的定義(由於函數的定義是直接寫在script標籤內的,所以該函數屬於window對象的一個屬性),再執行script中的代碼。
所以當遇到下一個script標籤時,由於之前的定義已經在window屬性中,所以調用不會報錯。注意:javascript引擎並不會一次性將所有script載入進來,先處理函數定義,
再調用(經過這次的測試後,筆者的見解)。
解釋Test 1的解析過程
javascript引擎遇到part1位置的script標籤時,先定義method1函數,並且將method1函數 賦值給window對象的同名屬性(這個賦給window對象屬性這個說法可能不恰當)。
由於part1位置的script標籤內,沒有代碼可以執行。。所以往下解析...遇到了<script src="method2.js"> 將method2.js載入進來,之後的處理同part1部分。
遇到part3部分,處理method3函數的定義,賦給window對象同名屬性,再執行method1(); method2();method3(); 後台應該是執行了window.method1();window.method2();
window.method3(); 結果為 method1~~ method2~~ method3~~