档时实时运行的查询。例如,下列代码会导致无限循环:
var divs = document.getElementsByTagName("div"), i, div; for (i=0; i < divs.length; i++){ div = document.createElement("div"); document.body.appendChild(div); }
第一行代码会取得文档中所有<div>元素的HTMLCollection。由于这个集合是“动态的”,因此
只要有新<div>元素被添加到页面中,这个元素也会被添加到该集合中。浏览器不会将创建的所有集
合都保存在一个列表中,而是在下一次访问集合时再更新集合。结果,在遇到上例中所示的循环代码
时,就会导致一个有趣的问题。每次循环都要对条件i < divs.length 求值,意味着会运行取得所
有<div>元素的查询。考虑到循环体每次都会创建一个新<div>元素并将其添加到文档中,因此
divs.length 的值在每次循环后都会递增。既然i 和divs.length 每次都会同时递增,结果它们的
值永远也不会相等。
如果想要迭代一个NodeList,最好是使用length 属性初始化第二个变量,然后将迭代器与该变
量进行比较,如下面的例子所示:
var divs = document.getElementsByTagName("div"), i, len, div; for (i=0, len=divs.length; i < len; i++){ div = document.createElement("div"); document.body.appendChild(div); }
10.3
小结
DOM 是语言中立的API,用于访问和操作HTML 和XML 文档。DOM1 级将HTML 和XML 文档
形象地看作一个层次化的节点树,可以使用JavaScript 来操作这个节点树,进而改变底层文档的外观和
结构。
DOM 由各种节点构成,简要总结如下。
最基本的节点类型是Node,用于抽象地表示文档中一个独立的部分;所有其他类型都继承自
Node。
Document 类型表示整个文档,是一组分层节点的根节点。在JavaScript 中,document 对象是
Document 的一个实例。使用document 对象,有很多种方式可以查询和取得节点。
Element 节点表示文档中的所有HTML 或XML 元素,可以用来操作这些元素的内容和特性。
另外还有一些节点类型,分别表示文本内容、注释、文档类型、CDATA 区域和文档片段。
访问DOM 的操作在多数情况下都很直观,不过在处理<script>和<style>元素时还是存在一些
复杂性。由于这两个元素分别包含脚本和样式信息,因此浏览器通常会将它们与其他元素区别对待。这
些区别导致了在针对这些元素使用innerHTML 时,以及在创建新元素时的一些问题。
理解DOM 的关键,就是理解DOM 对性能的影响。DOM 操作往往是JavaScript 程序中开销最大的
部分,而因访问NodeList 导致的问题为最多。NodeList 对象都是“动态的”,这就意味着每次访问
NodeList 对象,都会运行一次查询。有鉴于此,最好的办法就是尽量减少DOM 操作。