深入理解javascript中的动态集合——NodeList、HTMLCollection和NamedNodeMap
前面的话
一说起动态集合,多数人可能都有所了解。但是,如果再深入些,有哪些动态集合,以及这些动态集合有什么表现、区别和联系?可能好多人就要摇头了。本文就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的更多相关文章
- 深入理解JavaScript中创建对象模式的演变(原型)
深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...
- 深入理解JavaScript中的属性和特性
深入理解JavaScript中的属性和特性 JavaScript中属性和特性是完全不同的两个概念,这里我将根据自己所学,来深入理解JavaScript中的属性和特性. 主要内容如下: 理解JavaSc ...
- 深入理解javascript中执行环境(作用域)与作用域链
深入理解javascript中执行环境(作用域)与作用域链 相信很多初学者对与javascript中的执行环境与作用域链不能很好的理解,这里,我会按照自己的理解同大家一起分享. 一般情况下,我们把执行 ...
- 深入理解JavaScript中的作用域和上下文
介绍 JavaScript中有一个被称为作用域(Scope)的特性.虽然对于许多新手开发者来说,作用域的概念并不是很容易理解,我会尽我所能用最简单的方式来解释作用域.理解作用域将使你的代码脱颖而出,减 ...
- 理解JavaScript中的原型继承(2)
两年前在我学习JavaScript的时候我就写过两篇关于原型继承的博客: 理解JavaScript中原型继承 JavaScript中的原型继承 这两篇博客讲的都是原型的使用,其中一篇还有我学习时的错误 ...
- 【干货理解】理解javascript中实现MVC的原理
理解javascript中的MVC MVC模式是软件工程中一种软件架构模式,一般把软件模式分为三部分,模型(Model)+视图(View)+控制器(Controller); 模型:模型用于封装与应用程 ...
- 理解javascript中的策略模式
理解javascript中的策略模式 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换. 使用策略模式的优点如下: 优点:1. 策略模式利用组合,委托等技术和思想,有效 ...
- 深入理解javascript中的立即执行函数(function(){…})()
投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014-06-12 我要评论 这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是 ...
- 转载 深入理解JavaScript中的this关键字
转载原地址: http://www.cnblogs.com/rainman/archive/2009/05/03/1448392.html 深入理解JavaScript中的this关键字 1. 一 ...
随机推荐
- JavaScript读书笔记(一)
自动类型转换 在JavaScript中,使用 == .=== 和 - 等运算符能够使得类型自动转换. 关于不同类型的值的比较 flase == 0; //true "" == fl ...
- 【总结】C# Access 数据库 增删查改 的简单步骤
引用集: using System.Data.OleDb; static string exePath = System.Environment.CurrentDirectory;//本程序所 ...
- python RecursionError: maximum recursion depth exceeded in comparison错误
处理快速排序,递归深度可能非常大,而系统默认的深度可能没有这么大 需要设置最大递归深度 import sys sys.setrecursionlimit(100000) # 这个值的大小取决你自己,最 ...
- dictionary 应用(绑定dgv)
dictionary的用法://初始化添加所有车位进这队列 Utility.Effectlist.Add(); //每触发一次,用这个增加数量 Utility.Effectlist["Car ...
- 【转】stopPropagation, preventDefault 和 return false 的区别
因为有父, 子节点同在, 因为有监听事件和浏览器默认动作之分. 使用 JavaScript 时为了达到预期效果经常需要阻止事件和动作执行. 一般我们会用到三种方法, 分别是 stopPropagat ...
- PHP去重算法的优化过程
最近公司在做一个项目,需要对爬取到的数据进行去重,方法就是根据数据的id,去除掉id重复的数据. 下面是这个方法的演化过程. // 去重 $arr_id = array(); $LeTVFeedLis ...
- HDU1401 BFS
Solitaire Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total S ...
- WPF整理-跨程序集访问资源
“Sometimes binary resources are defined in one assembly (typically a class library), but areneeded i ...
- iOS单例详解
单例:整个程序只创建一次,全局共用. 单例的创建 // SharedPerson.h 文件中 + (instancetype)share; // SharedPerson.m 文件中 static S ...
- 【开源】MQTT推送服务器——zer0MqttServer(Java编写)
目录 说明 功能 如何使用 参考帮助 说明 重要的放前面:V1.0版本是一个非常基础的版本,除了完整的MQTT协议实现外,其他功能什么都没做. MQTT 协议是 IBM 开发的即时通讯协议,相对于 I ...