在Javascript中有一些看起来像数组的变量,比如函数内的arguments变量、getElementsByTagName()的返回值等,它们有length属性,也可以通过arguments[0]的形式读取其中的某一项,但它们并不是数组,并没有push、pop等数组所具有的方法。 getElementsByTagName()的返回值是NodeList类型的对象,此外,文档节点的childNodes属性也是NodeList类型。除了不是数组以外,它们还具有特殊的性质——它们是动态的,对文档的任何改变都会实时反映到NodeList中。下面举个例子说明一下:

    <ul id="ul">
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
    </ul>
    <script>
    var ul = document.getElementById('ul');
    var list = document.getElementsByTagName('li');
    for (var i=0; i<list.length; i++) {
        ul.appendChild(list[i]);
    }
    </script>

看看运行结果是什么

  • 2
  • 4
  • 1
  • 5
  • 3

这个结果是不是有点出乎意料?但是结合上面描述的NodeList的特性就不难理解,由于list是动态的,所以每次循环都改变了列表,过程如下:

i= list顺序
0 1 2 3 4 5
1 2 3 4 5 1
2 2 4 5 1 3
3 2 4 1 3 5
4 2 4 1 5 3

由于NodeList是动态的特性,常常会产生出乎意料的结果,所以我们使用前可以将它转成普通的数组:

    list = Array.prototype.slice.call(list);

此外,我们可以使用querySelectorAll()来代替getElementsByTagName()querySelectorAll()返回值也是NodeList类型,但却是静态的NodeList,不会随着文档的变化而改变。如可以把代码改成:

    var list = document.querySelectorAll('li');

这样改写后就能得到我们想要的结果:

  • 1
  • 2
  • 3
  • 4
  • 5

另一种行为很类似的数据类型是HTMLCollection,document的许多属性都是HTMLCollection对象,例如document.all, document.forms, document.images, document.links, document.anchors等,还有Form.elements, Select.options等,它们也是动态的,与NodeList不同的是,HTMLCollection对象是只读的,不能给它添加新元素。

此外,除了通过index来获取元素以外,还可以通过id或者name来获取元素,如document.all[‘main’],如果查找到id值相匹配的元素,则返回该元素,否则查找name值相匹配的元素,如果仍没找到,则返回null。