getElementsByTagName/getElementsByName/getElementsByClassName方法的返回值是HTMLCollection、或者是NodeList对象。但是,请注意,这个HTMLCollection/NodeList对象是「活性(Live)对象」。
「活性」是指「对象引用着文档树,对文档树所做的变更会实时反映到HTMLCollection/NodeList对象中」。
例如,我们来看下下面这个代码。
●清单6-33 live.html(上)/live.js(下)
自学PHP 第3版
Java口袋参考手册
Swift口袋参考手册
自学ASP.NET 第5版
制作应用吧!Android入门
'变更前:' // 结果:
'变更后:' // 结果:
我们可以看到,通过使用appendChild方法添加<li>
元素,HTMLCollection对象list的内容也产生了「5 → 6」的变化。这就是为什么说HTMLCollect对象是活性对象。
虽然乍一看HTMLCollection对象的这个特性很方便,但也有必须注意的点。例如,下面是将从<ul id="first">
元素中取出的<li>
元素添加到<ul id="second">
元素中的例子。
自学PHP 第3版
Java口袋参考手册
Swift口袋参考手册
自学ASP.NET 第5版
制作应用吧!Android入门
代码预期是想将<ul id="first">
元素中的<li>
元素复制到<ul id="second">
元素中,但是这个代码并没有正确运行。因为HTMLCollection对象是活性对象,所以①中for循环时,节点的个数(li.length)也会产生变化。因此,for循环的结束条件「i < li.length」为false,成为了无限循环。
将②的代码如下改写可以避免这个问题。
for(var i = 0, len = li.length; i < len; i++) {
初始化表达式中将length属性的值存储在变量len中,所以length属性的变化就不会影像到结束条件了。
另外,正如2.5.6中所接触到的,原本访问length属性就是开销相当大的处理。从性能的角度来看,相比在结束表达式中每次计算,在初始化表达式中访问一次更有利,所以优先将这种写法记为基础写法。
Note querySelectorAll方法的返回值
querySelectorAll方法也是将获取的节点组作为NodeList对象返回的。但是,这里的NodeList对象称为「静态NodeList」,文档树的变化不会影响对象。也就是说是将相关的节点都进行复制然后另存的对象。