[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); // 显示了断言。调用错误
```