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 对象作为对比,如下图所示:

33.png

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

HTMLCollection

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

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

<div id="test"></div>
<script>
var childN = test.children;
//IE7-浏览器并未定义HTMLCollection对象,会报错,其他浏览器返回true
alert(childN instanceof HTMLCollection);
var tags =test.getElementsByTagName('div');
//IE7-浏览器并未定义HTMLCollection对象,会报错,其他浏览器返回true
alert(tags instanceof HTMLCollection);
</script> 

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 <len; i++) {
                array.push(nodes[i]);
            }
        }
    }
var ff = convertToArray(nodes);
console.log(ff instanceof Array);  //true

因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 内容。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • DOM(文档对象模型)是针对 HTML 和 XML 文档的一个 API。DOM 描绘了一个层次化的节点树,允许开发...
    劼哥stone阅读 908评论 8 6
  • 如果你是夜 那我就此刻醒來
    袁鸣川阅读 239评论 3 3
  • linux系统 1.1认识linux 1.1.1什么是操作系统 1.1.2 现实生活中的操作系统 w7,mac,a...
    程猿先生阅读 406评论 0 0
  • 故事感悟人生,声音传递温暖。 有人说,不关注自己的心灵,无法得到真正的快乐和自由; 也有人说,这个世界不适合清醒的...
    云渊上神阅读 594评论 0 50
  • “哇,520了嘢,我要去告白!”“520了,我要不要去找女神约会,嘿嘿~” 哦好吧,我已经习惯了我们天朝的创造力了...
    不正式青年阅读 3,326评论 3 3

友情链接更多精彩内容