前面的话

  一说起动态集合,多数人可能都有所了解。但是,如果再深入些,有哪些动态集合,以及这些动态集合有什么表现、区别和联系?可能好多人就要摇头了。本文就javascript中的动态集合做详细介绍

NodeList

  NodeList实例对象是一个类数组对象,它的成员是节点对象,包括childNodes和querySelectorAll()方法返回值

<div id="test"></div>
<script>
console.log(test.childNodes);//[]
//IE7-浏览器并未定义NodeList对象,会报错,其他浏览器返回true
console.log(test.childNodes instanceof NodeList)
</script>
<div id="test"></div>
<script>
console.log(document.querySelectorAll('div'));//[div#test]
//IE8-浏览器不支持querySelectorAll()方法,返回false,其他浏览器返回true
console.log(document.querySelectorAll('div') instanceof NodeList)
</script>

  动态集合是指DOM结构的变化能够自动反映到所保存的对象中

<div id="test"></div>
<script>
var childN = test.childNodes;
console.log(childN);//[]
test.appendChild(document.createElement('div'));
console.log(childN);//[div]
</script>

静态

  [注意]NodeList并不都是动态集合,其中querySelectorAll()返回值就是静态集合NodeStaticList

<div id="test"></div>
<script>
var seles = test.querySelectorAll('div');
console.log(seles);//[]
test.appendChild(document.createElement('div'));
console.log(seles);//[]
console.log(test.querySelectorAll('div'));//[div]
</script>

数组

  由于NodeList是类数组对象,并不是真正的数组对象,可以使用slice()方法将其变成真正的数组

<div id="test"></div>
<script>
var childN = test.childNodes;
console.log(childN instanceof Array);//false
var childNew = Array.prototype.slice.call(childN);
console.log(childNew instanceof Array);//true
</script>

  但是,由于IE8-浏览器将NodeList实现为一个COM对象,不能使用Array.prototype.slice()方法,必须手动枚举所有成员

<div id="test"></div>
<script>
var childN = test.childNodes;
console.log(childN instanceof Array);//false
function convertToArray(nodes){
var array = null;
try{
array = Array.prototype.slice.call(nodes)
}catch(ex){
array = [];
var len = nodes.length;
for(var i = 0; i < len; i++){
array.push(nodes[i]);
}
}
return array;
}
var childNew = convertToArray(childN);
console.log(childNew instanceof Array);//true
</script>

HTMLCollection

  HTMLCollection对象与NodeList对象类似,也是节点的集合,返回一个类数组对象。但二者有不同之处

  NodeList集合主要是Node节点的集合,而HTMLCollection集合主要是Element元素节点的集合。Node节点共有12种,Element元素节点只是其中一种。关于12种节点类型的详细信息移步至此

  HTMLCollection集合包括getElementsByTagName()、getElementsByClassName()、getElementsByName()等方法的返回值,以及children、document.links、document.forms等元素集合

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

动态

  与NodeList对象不同,所有的HTMLCollection对象都是动态的

<div id="test"></div>
<script>
var childN = test.children;
var tags =test.getElementsByTagName('div');
console.log(childN,tags);//[]、[]
test.innerHTML = '<div></div>';
console.log(childN,tags);//[div]、[div]
</script>

  [注意]与NodeList对象类似,要想变成真正的数组Array对象,需要使用slice()方法,在IE8-浏览器中,则必须手动枚举所有成员

NamedNodeMap

  可能一些人没有听过NamedNodeMap对象,该对象的常见实例对象是attributes属性

<div id="test"></div>
<script>
var attrs = test.attributes;
console.log(attrs instanceof NamedNodeMap);//true
</script>

动态

  该对象也是一个动态集合

<div id="test"></div>
<script>
var attrs = test.attributes;
console.log(attrs);//NamedNodeMap {0: id, length: 1}
test.setAttribute('title','123');
console.log(attrs);//NamedNodeMap {0: id, 1: title, length: 2}
</script>

注意事项

  动态集合是个很实用的概念,但在使用循环时一定要千万小心。可能会因为忽略集合的动态性,造成死循环

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的次数。因为每次访问它们,都会运行一次基于文档的查询。所以,可以考虑将它们的值缓存起来

最后

  NodeList是节点的集合,HTMLCollection是元素节点的集合,NamedNodeMap是特性节点的集合,它们都是类数组对象

  对了,还有一个更经典的类数组对象——函数内部的arguments,它也具有动态性

  欢迎交流

深入理解javascript中的动态集合——NodeList、HTMLCollection和NamedNodeMap的更多相关文章

  1. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

  2. 深入理解JavaScript中的属性和特性

    深入理解JavaScript中的属性和特性 JavaScript中属性和特性是完全不同的两个概念,这里我将根据自己所学,来深入理解JavaScript中的属性和特性. 主要内容如下: 理解JavaSc ...

  3. 深入理解javascript中执行环境(作用域)与作用域链

    深入理解javascript中执行环境(作用域)与作用域链 相信很多初学者对与javascript中的执行环境与作用域链不能很好的理解,这里,我会按照自己的理解同大家一起分享. 一般情况下,我们把执行 ...

  4. 深入理解JavaScript中的作用域和上下文

    介绍 JavaScript中有一个被称为作用域(Scope)的特性.虽然对于许多新手开发者来说,作用域的概念并不是很容易理解,我会尽我所能用最简单的方式来解释作用域.理解作用域将使你的代码脱颖而出,减 ...

  5. 理解JavaScript中的原型继承(2)

    两年前在我学习JavaScript的时候我就写过两篇关于原型继承的博客: 理解JavaScript中原型继承 JavaScript中的原型继承 这两篇博客讲的都是原型的使用,其中一篇还有我学习时的错误 ...

  6. 【干货理解】理解javascript中实现MVC的原理

    理解javascript中的MVC MVC模式是软件工程中一种软件架构模式,一般把软件模式分为三部分,模型(Model)+视图(View)+控制器(Controller); 模型:模型用于封装与应用程 ...

  7. 理解javascript中的策略模式

    理解javascript中的策略模式 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换. 使用策略模式的优点如下: 优点:1. 策略模式利用组合,委托等技术和思想,有效 ...

  8. 深入理解javascript中的立即执行函数(function(){…})()

    投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014-06-12 我要评论 这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是 ...

  9. 转载 深入理解JavaScript中的this关键字

    转载原地址: http://www.cnblogs.com/rainman/archive/2009/05/03/1448392.html 深入理解JavaScript中的this关键字   1. 一 ...

随机推荐

  1. Docker 创建php 开发环境遇到的权限问题解决方案

    最近我将公司的开发,和测试环境都运行到docker 上面,因为开发,测试基本都是装代码拉到本址,然后,再装目录,挂载到镜像目录中如:我用的是docker-compose # development.y ...

  2. Linux Shell 编程中的特殊符号

    一.井号 # 1.在脚本文件中对一行进行注释. 2.在引号和\符号后不是注释,只是#号本身: echo "12 # hehe" echo '12 # hehe' echo 12 \ ...

  3. 【hihoCoder】1036 Trie图

    题目:http://hihocoder.com/problemset/problem/1036 给一个词典dict,词典中包含了一些单词words.要求判断给定的一个文本串text中是否包含这个字典中 ...

  4. ThreadLocal类详解:原理、源码、用法

    以下是本文目录: 1.从数据库连接探究 ThreadLocal 2.剖析 ThreadLocal 源码 3. ThreadLocal 应用场景 4. 通过面试题理解 ThreadLocal 1.从数据 ...

  5. 如何用js得到当前页面的url信息方法(JS获取当前网址信息)

    设置或获取对象指定的文件名或路径. alert(window.location.pathname) 设置或获取整个 URL 为字符串. alert(window.location.href); 设置或 ...

  6. Sublime Text 3 配置和使用方法

    下载: Sublime Text 3 官方下载地址 Sublime Text 3 汉化破解版 资料: Sublime Text 非官方文档   技巧 -用户或-User后缀的菜单项,其对应的配置文件都 ...

  7. 不能链接云服务器mysql

    如果报host'' 不允许连接MySQL服务器  1130 错误的话如果你的3306端口打开了,也把user 里的host改为% 还是不行的话,请记得更改 站点域名设置,和你服务器相同,端口一致.

  8. Replace 删除、替换函数精解示例

    '************************************************************************* '**模 块 名:Replace函数精解示例 '* ...

  9. IOS第二天-新浪微博 - 添加搜索框,弹出下拉菜单 ,代理的使用 ,HWTabBar.h(自定义TabBar)

    ********HWDiscoverViewController.m(发现) - (void)viewDidLoad { [super viewDidLoad]; // 创建搜索框对象 HWSearc ...

  10. 《Linux内核设计与实现》读书笔记 第四章 进程调度

    第四章进程调度 进程调度程序可看做在可运行太进程之间分配有限的处理器时间资源的内核子系统.调度程序是多任务操作系统的基础.通过调度程序的合理调度,系统资源才能最大限度地发挥作用,多进程才会有并发执行的 ...