一直對js的載入和執行過程比較模糊,現在從幾個簡單例子看看javascript的載入和執行過程。
例一:
<script type="text/javascript">
alert($); // error: $未定義,後面的指令碼也無法執行
alert("我要執行");//不執行
</script>
<script src="http://tp.jrj.com.cn/js/jquery.js"></script>
<script type="text/javascript">
alert($); // function
</script>
結果及分析:script按順序載入,每個script載入完即執行,如果執行有錯會終止當前script的執行,對其它script沒有影響。
jquery載入完成才執行後面的alert($);
例二:
<script type="text/javascript">
alert(i); // undefined
var i = 1;
alert(i);
</script>
輸出結果是 undefined,這是因為執行前script引擎先對指令碼片段就行了"預解析"。預解析發生在文法分析階段,文法分析得到變數表varDecls,函數funDecls,父級引用upvalue
等文法分析結構,並儲存在文法樹中。從上到下執行,雖然執行環境中已經有了i的變數定義但未初始化,所以輸出為undefined
例三:
<script type="text/javascript">
alert(i); // error: i未定義
i = 1;
alert(i);
</script>
執行報錯。執行環境的scriptObject上找不到i,JS引擎再沿著scriptObject的upvalue往上尋找,最終在全域環境的scriptObject上都找不到,就產生執行階段錯誤,終止指令碼段執行。
再來看
<script src="http://tp.jrj.com.cn/js/jquery.js"></script>
<div style="border:1px solid red;width:100px;height:100px">
1111
</div>
<img src="http://www.meinvnv.com/uploads/allimg/100325/1_100325043702_1.jpg"/>
<script type="text/javascript">
alert($); // function
</script>
jquery載入完後div才被渲染,同樣img也是在jquery載入完後載入的。script載入執行時阻塞頁面的渲染和資源載入。指令碼可能改變文檔流,甚至跳轉頁面,所以瀏覽器暫停是合理的。
小結:
1) 如果一個文檔流中包含多個script程式碼片段(用script標籤分隔的js代碼或引入的js檔案),運行順序是:
step1. 載入、讀入第一個程式碼片段
step2. 做文法分析,對var變數和function定義做“預解析”,
有錯則報語法錯誤(比如括弧不匹配等),並跳轉到step4
step3. 執行程式碼片段,有錯則報錯(比如變數未定義)
step4. 如果還有下一個程式碼片段,則讀入下一個程式碼片段,跳到step2
step5. 結束
2) 指令碼片段執行時,阻塞後面資源的渲染和載入。