zoukankan      html  css  js  c++  java
  • 深入理解javascript中的动态集合——NodeList、HTMLCollection和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

  • 相关阅读:
    解决ubuntu不能安装g++的问题
    解决VMware虚拟机不能上网的问题
    打开vmvare出现The VMware Authorization Service is not running。
    word2-寻找社交新浪微博中的目标用户
    新浪云计算SAE部署代码过程
    Python如何调用新浪api接口的问题
    work1-英语辅导班在线报名系统
    Mysql对自增主键ID进行重新排序
    如何使用LIBSVM,从安装到基本实例使用
    laravel怎么创建一个简单的blog
  • 原文地址:https://www.cnblogs.com/bobonote/p/7867976.html
Copyright © 2011-2022 走看看