上篇文章以arguments为例讲到了类数组对象,这篇我们讨论更多的类数组对象NodeList、HTMLCollection和NamedNodeMap。既然是类数组对象,这3种对象也都能应用上篇文章中提到的类数组对象的可用方法,下面主要讲讲这3种对象的应用及区别。
HTMLCollection
可以从字面上理解,也就是HTML元素的集合,是一个类数组对象。一般包括getElementsByTagName()、getElementsByClassName()、getElementsByName()等方法的返回值,以及children、document.links、document.forms等元素集合。
<div></div> <div></div> <script> var divs = document.getElementsByTagName("div"); console.log(Array.prototype.toString.call(divs));//"[object HTMLCollection]" console.log(divs.length);//2 </script>
HTMLCollection是动态的,也就是说对其的增删改都会更新到这个类数组对象中。
<div></div> <div></div> <script> var divs = document.getElementsByTagName("div"); var newDiv = document.createElement("div"); divs[0].parentNode.appendChild(newDiv);//添加一个新div console.log(divs);//[div,div,div] </script>
NodeList
同样可以从字面上理解,节点集合,是一个类数组对象,通常由childNodes和querySelectorAll()返回。与HTMLCollection不同的是,NodeList是Node集合,包括但不仅限于HTMLCollection中的元素节点,还可以是其他节点。Node节点共有12种,这里不详细介绍。
<div> <p></p> </div> <script> var divs = document.getElementsByTagName("div"); //childNode返回值 console.log(Array.prototype.toString.call(divs[0].childNodes));//"[object NodeList]" console.log(divs[0].childNodes);//[text,p,text] //querySelectorAll返回值 console.log(Array.prototype.toString.call(document.querySelectorAll("p")));//"[object NodeList]" console.log(document.querySelectorAll("p"));//[p] </script>
要注意一点,NodeList不像HTMLCollection都是动态的,通过querySelectorAll()返回的NodeList是静态的,相当于获取时刻的一个快照。
<div> <p></p> </div> <script> var divs = document.getElementsByTagName("div"); var listChild = divs[0].childNodes; var listQuery = document.querySelectorAll("p"); divs[0].appendChild(document.createElement("p")); //childNodes返回值为动态的,增加了一个p元素 console.log(listChild);//[text,p,text,p] //querySelectorAll返回值为静态,没有变化 console.log(listQuery);//[p] </script>
NamedNodeMap对象
NamedNodeMap对象比较少见,较为常见的是其实例对象attributes属性。
<div id="myDiv" class="bd"></div> <script> var div = document.getElementById("myDiv"); var attrs = div.attributes; console.log(Array.prototype.toString.call(attrs));//"[object NamedNodeMap]" console.log(attrs);// {0: id, 1: class, length: 2} </script>
NamedNodeMap也是动态的
<div id="myDiv" class="bd"></div> <script> var div = document.getElementById("myDiv"); var attrs = div.attributes; div.title = "hello"; console.log(attrs);//{0: id, 1: class, 2: title, length: 3} </script>
注意:这3种对象基本都是动态集合(querySelectorAll获得的NodeList为静态),这会带来一些便利,但也会带来较大的性能开销。每次访问这类动态集合,都会执行一次文档的搜索,因此要尽量减少DOM操作。而对于与其相关的定值,比如divs.length,若需多次使用,可以考虑将其值缓存起来,以免每次应用时都要进行一次查询。