JavaScript 之动态集合

第一次读《JavaScript高级程序设计(第三版)》,没怎么注意和理解JavaScript 动态集合的概念,最近二次阅读这本书,想进一步对其做深入的研究。现于此细究一下这三个动态集合(HTMLCollection、NodeList、NodeNameMap)之间的用法和联系及区别。

这里的动态集合是指:DOM结构的变化能够自动反应到所保存的对象中。

NodeList

NodeList 是一种类数组对象,是node节点(12种)的集合,用于保存一组有序的节点,可以通过节点的位置访问这些节点。在childNodes属性和querySelectorAll()方法返回值中保存着 NodeList 对象。

在childNodes属性中的NodeList对象

var div = document.getElementById("div1");
var children = div.childNodes;         //获取div元素子节点集合
alert(children instanceof NodeList);   //true

通过querySelectAll()方法返回值中的NodeList对象

var divs = documene,qrerySelectAll('div');
alert(divs.instance of NodeList)  //true

这里需要注意的是通过querySelectorAll()方法返回值中保存着 NodeList 对象是静态集合;这里可以与下文中的HTMLCollection 对象作为对比,如下图所示:

JavaScript 之动态集合_第1张图片
33.png

如此就可以看出两者之间“动态”和“静态”的区别。

HTMLCollection

HTMLCollection对象与NodeList对象类似,都是节点的集合,返回的都是类数组对象。但他们也存在着不同之处:NodeList集合包含着node节点中12种节点,而HTMLCollection 仅包含elements 元素节点的集合。

HTMLCollection对象包含于getElemenstByTagName()、getElementsByClassName()、getElementsByName()等方法返回的值,以及children、document.links、document.forms等元素集合。

NameNodeMap

这个对象包含于attributes 属性中,元素的每一个特性都由一个Attr 节点表示,每个节点都保存在 NameNodeMap 对象中。

var div = document.getElementById("div1");
var attrs = div.attributes;            //获取div元素的特性
alert(children instanceof NamedNodeMap);  //true

类数组转数组的方法

之前了解 arguments 对象的都知道,它是一个类数组对象,有数组的表达方式,但并没有数组方法。而HTMLCollection、NodeList、NodeNameMap 这三者同样与 arguments 对象一样。因此必须将其实现由类数组转化为数组:

function convertToArray(nodes) {
    var array = null;
    try {
        array = nodes.prototype.slice.call(nodes, 0);
    } catch {  
//由于IE8-浏览器将NodeList实现为一个COM对象,不能使用Array.prototype.slice()方法,必须手动枚举所有成员。
       array = new Array();
       for(var i = 0, len =  nodes.length; i 

因DOM操作是往往是JavaScript 程序中开销最大的部分,因此在循环遍历这些动态集合时,不要忽略其动态性,从而避免穿死循环,如下两段代码对比:

var divs = document.getElementsByTagName("div");
for(var i = 0 ; i < divs.length; i++){
 document.body.appendChild(document.createElement("div"));
}

在上面代码中,由于divs是一个HTMLElement集合,divs.length会随着appendChild()方法,而一直增加,于是变成一个死循环。
为了避免此种情况发生,代码改进如下:

var divs = document.getElementsByTagName("div");
for(var i = 0,len = divs.length; i < len; i++){
 document.body.appendChild(document.createElement("div"));
}

一般地,要尽量减少访问NodeList、HTMLCollection、NamedNodeMap的次数。因为每次访问它们,都会运行一次基于文档的查询。所以,可以考虑将它们的值缓存起来。

对于JavaScript 的动态集合就总结这么多,若有纰漏方请指正,后期后跟进补充其它的JavaScript 内容。

你可能感兴趣的:(JavaScript 之动态集合)