目录
一、动态集合的概念
dom将页面解析成一个由多层次节点构成的结构即dom结构。节点是dom结构的基础。dom中动态集合是指能够自动映射dom节点变化的集合。dom中有三种常用的动态集合,分别是节点集合NodeList、元素节点集合HTMLCollection和特性节点集合NamedNodeMap。Javascript中的动态集合都是类数组。
与动态集合相对的是静态集合,dom中静态集合不能够自动映射dom节点变化,仅仅只是一组节点快照。
二、NodeList
NodeList是节点集合,集合中的元素可以是任意类型的Node节点。NodeList集合是一个类数组,有两种方式可以访问集合元素,其一使用方括号,其二使用item()方法。Javascript中常见的有两种方式获取NodeList集合。其一通过节点属性childNodes,其二通过selector选择器querySelectorAll()。NodeList在ie7及以下版本的浏览器中不兼容。
NodeList集合分为两类,其一是动态集合,其二是静态集合。childNodes属性返回的结果是动态集合,querySelectorAll()返回的结果是静态集合。
实例对象
childNodes
dom有12种节点类型,所有类型的节点最终都继承自Node节点类,因此所有类型的节点都共享着基本的属性和方法。childNodes是一个定义在Node节点类上的属性,通过该属性可以得到一个保存着当前节点所有子节点的NodeList集合。
<div>
<span></span>
</div>
<script>
var div = document.getElementsByTagName("div")[0];
console.log(div.childNodes); //NodeList(3) [text, span, text]
</script>
childNodes属性返回的结果是一个动态集合,会自动映射dom节点变化。
<div></div>
<script>
var div = document.getElementsByTagName("div")[0];
var childs = div.childNodes;
console.log(childs); //NodeList []
div.appendChild(document.createElement("span"));
console.log(childs); //NodeList [span]
</script>
querySelectorAll()
该选择器返回的结果是一个静态的NodeList集合,不能自动映射dom节点变化,相当于一组dom节点的快照。
<div id="div"></div>
<script>
var nodes = document.querySelectorAll("div");
console.log(nodes); //NodeList [div#div]
div.appendChild(document.createElement("div"));
console.log(nodes); //NodeList [div#div]
</script>
转换为数组
NodeList集合是一个类数组,可以使用slice()方法将其转换为真正的数组。但在ie7及以下版本的浏览器中NodeList被实现为一个COM对象,不支持slice()方法。兼容写法如下。
function nodeListToArray(nodes) {
var array = null;
try {
array = Array.prototype.slice.call(nodes);//ie7及以下版本浏览器不支持slice()
} catch (ex) {
array = new Array();
for (var i = 0, len = nodes.length; i < len; i++) {
array.push(nodes[i]);
}
}
return array;
}
属性和方法
<div>
<span>1</span>
<span>2</span>
<span>3</span>
</div>
<script>
var div = document.getElementsByTagName("div")[0];
var nodeLt = div.childNodes;
console.log(nodeLt.__proto__);
</script>
forEach()
forEach用于遍历集合中的节点,并将节点传递给回调函数(空集合不执行回调函数)。ie8及以下版本的浏览器不兼容。
语法:nodeList.forEach(function(currentNode, index, nodeList), thisValue)
1、参数1:function(currentValue, index, nodeList)
(1)概念:集合中每个节点需要调用的回调函数
(2)currentNode:必选,当前节点
(3)index:选填,当前节点的索引
(4)nodeList:选填,当前节点所属集合对象即调用forEach方法的集合本身
2、参数2:thisValue
(1)选填
(2)向回调函数额外传递的参数,函数内this指向该参数
(3)如果参数为空,回调函数内this指向undefined
<div>
<span>1</span>
<span>2</span>
</div>
<script>
var div = document.getElementsByTagName("div")[0];
var nodeLt = div.childNodes;
nodeLt.forEach(function(item, index, set){
console.log("当前节点名称:" + item.nodeName + ",索引:" + index);
});
/*
打印结果:
当前节点名称:#text,索引:0
当前节点名称:SPAN, 索引:1
当前节点名称:#text,索引:2
当前节点名称:SPAN, 索引:3
当前节点名称:#text,索引:4
*/
</script>
item()
根据索引值返回集合中的节点。索引超出集合范围时返回null。item方法很少使用,因为它与直接使用方括号作用一样。
<div>
<span>1</span>
<span>2</span>
</div>
<script>
var div = document.getElementsByTagName("div")[0];
var nodeLt = div.childNodes;
console.log(nodeLt.item(1)); //<span>1</span>
console.log(nodeLt.item(3)); //<span>2</span>
console.log(nodeLt.item(5)); //null
console.log(nodeLt[1]); //<span>1</span>
console.log(nodeLt[3]); //<span>2</span>
console.log(nodeLt[5]); //undefined
</script>
length属性
返回集合中节点的数量。
三、HTMLCollection
HTMLCollection是html元素节点的集合。HTMLCollection集合是一个类数组,有两种方式可以访问集合元素,其一使用方括号,其二使用item()方法。NodeList是dom节点集合,而HTMLCollection是Element元素节点集合,所以HTMLCollection相当于NodeList的子集。与NodeList集合不同,所有HTMLCollection集合都是动态的。HTMLCollection集合包括getElementsByTagName()、getElementsByClassName()、getElementsByName()等dom元素选择器的返回值,以及children、document.links、document.forms等html元素集合。与NodeList集合相同,HTMLCollection集合要想变成真正的数组,需要使用slice()方法,在ie7及以下版本的浏览器中,不支持slice()方法,必须手动枚举所有成员。
<div id="div">
<span id="s1">1</span>
<span id="s2">2</span>
<span id="s3">3</span>
</div>
<script>
var childs = div.children;
console.log(childs);
</script>
namedItem()
根据id或name属性查询集合中的元素,并返回第一个匹配的元素节点。该方法首先根据id属性匹配集合中的元素节点,如果匹配不成功,再根据name属性匹配元素节点,如果依旧不成功则返回null。所有主流浏览器都支持该方法。
<div id="d1"></div>
<div id="d2"></div>
<div name="d1"></div>
<script>
var set = document.getElementsByTagName("div");
console.log(set.namedItem("d1")); //<div id="d1"></div>
console.log(set["d1"]); //<div id="d1"></div>, namedItem方法的简写
</script>
<form>
<input id="i1"/>
</form>
<script>
var input = document.forms[0]['i1']; //<input id="i1"/>
</script>
四、NamedNodeMap
NamedNodeMap是特性节点的集合。最典型的实例对象是元素节点的attributes属性。该集合是一个类数组,有两种方式可以访问集合元素,其一使用方括号,其二使用item()方法。NamedNodeMap是一个动态集合。
<div id="d1"></div>
<script>
console.log(d1.attributes); //NamedNodeMap {0: id, id: id, length: 1}
d1.setAttribute("class","c1");
console.log(d1.attributes); //NamedNodeMap {0: id, 1: class, id: id, class: class, length: 2}
</script>
getNamedItem()
根据特性名从集合中返回指定的特性节点。所有主流浏览器都支持该方法。
<div id="d1"></div>
<script>
var attr = d1.attributes;
console.log(attr.getNamedItem("id")); // id="d1"
console.log(attr.getNamedItem("id").value); //"d1"
console.log(attr["id"]); //id="d1", getNamedItem的简写形式
</script>
item()
根据索引值返回集合中的节点。索引超出集合范围时返回null。item方法很少使用,应为它与直接使用方括号作用一样。
length属性
返回集合中节点的数量。
removeNamedItem()
根据特性名从集合中删除并返回指定的特性节点。所有主流浏览器都支持该方法。
<div id="d1"></div>
<script>
var attr = d1.attributes;
console.log(attr); //NamedNodeMap {0: id, id: id, length: 1}
console.log(attr.removeNamedItem("id")); // id="d1"
console.log(attr); //NamedNodeMap {length: 0}
</script>
setNamedItem()
向集合中添加新的特性节点。如果特性节点已经存在,将被替换并返回被替换的特性节点,如果特性节点不存在,则返回null。
<div id="d1"></div>
<script>
var attr = d1.attributes;
var node0 = document.createAttribute("class");
node0.nodeValue = "c1";
console.log(attr.setNamedItem(node0)); //null
var node1 = document.createAttribute("class");
node1.nodeValue = "c2";
console.log(attr.setNamedItem(node1)); //class="c1"
</script>