4 浏览器环境
4.1 DOM
4.1.1 元素获取
【建议】 对于单个元素,尽可能使用 document.getElementById
获取,避免使用document.all
。
【建议】 对于多个元素的集合,尽可能使用 context.getElementsByTagName
获取。其中 context
可以为 document
或其他元素。指定 tagName
参数为 *
可以获得所有子元素。
【建议】 遍历元素集合时,尽量缓存集合长度。如需多次操作同一集合,则应将集合转为数组。
解释:
原生获取元素集合的结果并不直接引用 DOM 元素,而是对索引进行读取,所以 DOM 结构的改变会实时反映到结果中。
示例:
<div></div>
<span></span>
<script>
var elements = document.getElementsByTagName('*');
// 显示为 DIV
alert(elements[0].tagName);
var div = elements[0];
var p = document.createElement('p');
docpment.body.insertBefore(p, div);
// 显示为 P
alert(elements[0].tagName);
</script>
【建议】 获取元素的直接子元素时使用 children
。避免使用childNodes
,除非预期是需要包含文本、注释和属性类型的节点。
4.1.2 样式获取
【建议】 获取元素实际样式信息时,应使用 getComputedStyle
或 currentStyle
。
解释:
通过 style 只能获得内联定义或通过 JavaScript 直接设置的样式。通过 CSS class 设置的元素样式无法直接通过 style 获取。
4.1.3 样式设置
【建议】 尽可能通过为元素添加预定义的 className 来改变元素样式,避免直接操作 style 设置。
【强制】 通过 style 对象设置元素样式时,对于带单位非 0 值的属性,不允许省略单位。
解释:
除了 IE,标准浏览器会忽略不规范的属性值,导致兼容性问题。
4.1.4 DOM 操作
【建议】 操作 DOM
时,尽量减少页面 reflow
。
解释:
页面 reflow 是非常耗时的行为,非常容易导致性能瓶颈。下面一些场景会触发浏览器的reflow:
- DOM元素的添加、修改(内容)、删除。
- 应用新的样式或者修改任何影响元素布局的属性。
- Resize浏览器窗口、滚动页面。
- 读取元素的某些属性(offsetLeft、offsetTop、offsetHeight、offsetWidth、scrollTop/Left/Width/Height、clientTop/Left/Width/Height、getComputedStyle()、currentStyle(in IE)) 。
【建议】 尽量减少 DOM
操作。
解释:
DOM 操作也是非常耗时的一种操作,减少 DOM 操作有助于提高性能。举一个简单的例子,构建一个列表。我们可以用两种方式:
- 在循环体中 createElement 并 append 到父元素中。
- 在循环体中拼接 HTML 字符串,循环结束后写父元素的 innerHTML。
第一种方法看起来比较标准,但是每次循环都会对 DOM 进行操作,性能极低。在这里推荐使用第二种方法。
4.1.5 DOM 事件
【建议】 优先使用 addEventListener / attachEvent
绑定事件,避免直接在 HTML 属性中或 DOM 的 expando
属性绑定事件处理。
解释:
expando 属性绑定事件容易导致互相覆盖。
【建议】 使用 addEventListener
时第三个参数使用 false
。
解释:
标准浏览器中的 addEventListener 可以通过第三个参数指定两种时间触发模型:冒泡和捕获。而 IE 的 attachEvent 仅支持冒泡的事件触发。所以为了保持一致性,通常 addEventListener 的第三个参数都为 false。