[TOC]
# 客戶端 JavaScript 與 HTML
## 網頁顯示過程中的處理流程
瀏覽器在訪問該頁面時執行了以下處理:
1. 分析HTML
2. 構造DOM樹
3. 載入外部 JavaScript 文件以及 CSS 文件
4. 載入圖像文件等外部資源
5. JavaScript 在分析后開始執行
6. 全部完成
要點在于圖像文件等內容是在構造完 DOM 樹之后才下載的,因此如果在構造完 DOM 樹后再執行 JavaScript,用戶等待時間就可以減少。
## 讀取外部 JavaScript 文件
對 `<script>` 標簽指定 `defer` 屬性和 `async` 屬性。通過指定 `defer` 屬性,可以使該 `<script>` 標簽的處理推遲至其他所有的 `<script>` 標簽之后。而如果指定了 `async` 屬性,則會以異步方式讀取外部文件,并在讀取完成后依次執行。
```html
<script src="http://xxx.js" defer></script>
<script src="http://xxx.js" async></script>
```
## 動態載入 JavaScript 文件
```javascript
var script = docuement.createElement('script');
script.src = "xxx.js";
document.getElementsByTagName('head')[0].appendChild(script);
```
這種方法執行 JavaScript 時,JavaScript 文件在下載過程中并不會阻斷其他的操作
## 顯示棧追蹤
使用 `console.trace()` 方法可以顯示函數的調用者,并可以據此了解具體是哪一個對象的哪一個事件觸發了該函數。
## 測量時間、次數與性能
### console.time() 與 console.timeEnd()
通過 `console.time()` 與 `console.timeEnd()` 方法測量經過這兩個方法之間經過的時間,參數分別為每次計時的名稱。具有相同名稱的方法將會配對,其間經過的時間則會輸出。時間的顯示單位為毫秒
```javascript
console.time('foo');
alert('foo計時開始');
console.timeEnd('foo');
```
### console.count()
通過 `console.count()` 可以知道該行具體執行了多少次
```javascript
for(var i = 0; i < 100; i++){
console.count('foo');
}
// foo: 100
```
### console.profile() 與 console.profileEnd()
通過 `console.profile()` 與 `console.profileEnd()` 可以獲得更為詳細的測量結果。可以獲取各個函數分別執行了多少次,或總的執行時間等信息。
## 使用斷言
`console.assert()` 的功能是僅在指定條件為 `false` 時輸出日志。
```javascript
function foo(notNullObj){
console.assert(notNullObj != null, 'not NullObj is null or undefined');
}
foo(1); // 顯示正確
foo(null); // 顯示了斷言。調用錯誤
```