深⼊理解javascript中的动态集合——NodeList、
HTMLCollection。。。
前⾯的话
⼀说起动态集合,多数⼈可能都有所了解。但是,如果再深⼊些,有哪些动态集合,以及这些动态集合有什么表现、区别和联系?可能好多⼈就要摇头了。本⽂就javascript中的动态集合做详细介绍
NodeList
NodeList实例对象是⼀个类数组对象,它的成员是节点对象,包括childNodes和返回值
<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.ateElement('div'));
console.log(childN);//[div]
</script>
静态
[注意]NodeList并不都是动态集合,其中querySelectorAll()返回值就是静态集合NodeStaticList
<div id="test"></div>
<script>
var seles = test.querySelectorAll('div');
console.log(seles);//[]
test.ateElement('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 =ElementsByTagName('div');
//IE7-浏览器并未定义HTMLCollection对象,会报错,其他浏览器返回true
console.log(tags instanceof HTMLCollection);
</script>
动态
与NodeList对象不同,所有的HTMLCollection对象都是动态的
<div id="test"></div>
javascript数组对象<script>
var childN = test.children;
var tags =ElementsByTagName('div');
console.log(childN,tags);//[]、[]
test.innerHTML = '<div></div>';
console.log(childN,tags);//[div]、[div]
</script>
[注意]与NodeList对象类似,要想变成真正的数组Array对象,需要使⽤slice()⽅法,在IE8-浏览器中,则必须⼿动枚举所有成员
NamedNodeMap
可能⼀些⼈没有听过NamedNodeMap对象,该对象的常见实例对象是
<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 = ElementsByTagName("div");
for(var i = 0 ; i < divs.length; i++){
document.body.ateElement("div"));
}
在上⾯代码中,由于divs是⼀个HTMLElement集合,divs.length会随着appendChild()⽅法,⽽⼀直增加,于是变成⼀个死循环
为了避免此情况,⼀般地,可以写为下⾯形式
var divs = ElementsByTagName("div");
for(var i = 0,len = divs.length; i < len; i++){
document.body.ateElement("div"));
}
⼀般地,要尽量减少访问NodeList、HTMLCollection、NamedNodeMap的次数。因为每次访问它们,都会运⾏⼀次基于⽂档的查询。所以,可以考虑将它们的值缓存起来
最后
NodeList是节点的集合,HTMLCollection是的集合,NamedNodeMap是的集合,它们都是类数组对象
对了,还有⼀个更经典的类数组对象——内部的,它也具有动态性
欢迎交流
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论