深入理解javascript中的动态集合——NodeListHTMLCollection和NamedNodeMap
Posted 苯宝宝
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入理解javascript中的动态集合——NodeListHTMLCollection和NamedNodeMap相关的知识,希望对你有一定的参考价值。
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,它也具有动态性
PS:原文https://www.cnblogs.com/xiaohuochai/p/5827389.html
以上是关于深入理解javascript中的动态集合——NodeListHTMLCollection和NamedNodeMap的主要内容,如果未能解决你的问题,请参考以下文章
Java 集合深入理解 :ArrayList源码解析,及动态扩容机制
深入理解JavaScript的闭包特性 如何给循环中的对象添加事件
深入理解java集合框架之---------Arraylist集合