• JS中的动态合集与静态合集


    JS的动态合集

    前言

    DOM是JavaScript重要组成部分,在DOM中有三个特别的集合分别是NodeList(节点的集合),NamedNodeMap(元素属性的集合)和HTMLCollection(html元素的集合)。这三个集合有一些共同的特点:它们都是一个类数组对象,可以通过中括号表达式来访问集合中元素,也有length属性。但它们并不是数组,而且它们都是动态的(querySelectorAll()返回的NodeList除外),会根据页面元素的变化而变化。下面就来介绍一下它们。

    NodeList集合

    如何获取NodeList集合

    DOM将HTML页面解析成一个由多层次节点构成的结构。节点是页面结构的基础,而所有节点继承自Node类型,因此所有节点共享着基本的属性和方法。Node类型有一个childNodes属性,所以所有节点都拥有这个属性。而通过这个属性就可以得到一个保存着本节点的子节点组成的NodeList对象。

    如何操作NodeList

    NodeList可以通过方括号表达式来访问,也可以通过item()方法来访问,也有length属性,可以访问元素个数。 虽然javascript中的数组可以修改length属性。但NodeList集合并不是数组,而且它是页面一片区域的DOM结构映射。所以请不要修改NodeList对象的length值。

    var firstChild = someNode.childNodes[0];//获取第一个元素
    var secondChild = someNode.childNodes.item(1);//获取第二个元素
    var count = someNode.childNodes.length;//获取集合长度

    NamedNodeMap

    如何获取NamedNodeMap

    Element类型这种DOM节点是唯一拥有attributes属性的一种节点类型。而attribute属性中就包含NamedNodeMap集合。它由元素的特性组成。所以只要是元素节点,调用attributes属性就可以得到NamedNodeMap集合。

    如何操作NamedNodeMap集合

    可能一些人没有听过NamedNodeMap对象,该对象的常见实例对象是attributes属性

    <div id="test"></div>
    <script>
        var attrs = test.attributes;
        console.log(attrs instanceof NamedNodeMap); //true
    </script>
    

    NamedNodeMap集合的元素拥有nodeName和nodeValue属性,分别表示元素特性名称和特性值,也拥有以下方法:

    • getNamedItem(name);返回nodeName属性等于name的节点;
    • removeNamedItem(name);从列表中移除nodeName节点;
    • setNamedItem(node);向列表中添加节点,以节点nodeName为属性索引;
    • item(pos);返回位于数字pos位置的节点。
    var className = element.attributes.getNamedItem('class').nodeValue;
    var className1 = element.attributes['class'].nodeValue;
    var oldAttr = element.attributes.removeNamedItem('class');
    

    一般元素节点的getAttribute()、removeAttribute()和setAttribute()方法都可以完成以上操作

    HTMLCollection

    如何得到HTMLCollection集合

    HTMLCollection是元素节点的集合可以通过getElementsByTagName()方法(获取同类型的元素)、getElementsByClassName()(获取class特性相同的元素)、getElementsByName()方法(获取name特性相同的元素)、document的anchors属性(包含name特性的a元素),forms属性(包含文档所有form元素),images属性(包含文档所有img元素),links属性(文档所有带href特性的a元素)。

    与NodeList区别

    NodeList集合主要是Node节点的集合,而HTMLCollection集合主要是Element元素节点的集合。Node节点共有12种,Element元素节点只是其中一种。

    注意事项

    这三个集合都是“动态的”;当文档结构发生变化时,它们都会更新,所以以下操作就会发生错误:

    var divs = document.getElementsByTagName('div');
    for (var i = 0; i < divs.length; i++) {
        var div = document.createElement('div');
        document.body.appendChild(div);
    }

    以上代码中的for循环将会一直执行,因为div得到的HTMLCollection集合是动态的,当每次给body添加元素divs都会进行更新,所以会一直循环下去。

    解决方法1:将初始的集合的length存起来

    var divs = document.getElementsByTagName('div');
    for (var i = 0, var len = divs.length; i < len; i++) {
        var div = document.createElement('div');
        document.body.appendChild(div);
    }

    解决方法2:将以上集合转化为数组

    var divs = document.getElementsByTagName('div');
    //将HTMLCollection转换为数组(此方法在IE8及以前不能用)
    var divsArr = Array.prototype.slice.call(divs,0);
    for (var i = 0; i < divsArr.length; i++) {
        var div = document.createElement('div');
        document.body.appendChild(div);
    }

    由于IE8-浏览器将NodeList实现为一个COM对象,不能使用Array.prototype.slice()方法,必须手动枚举所有成员

    将以上集合转为数组的方法(通用):

    function convertListToArray(nodes) {
       var array = null;
       try{//标准浏览器
           array = Array.prototype.slice.call(nodes,0);
       }catch(ex){//IE8及以下遍历每一项分别添加到数组中
           array = new Array();
           for(var i = 0,len = nodes.length;i < len;i++){
               array.push(nodes[i]);
           }
       }
       return array;
    }

    JS的静态合集

    前言

    除了getElementsByClassName()方法外,HTML5中DOM拓展了querySelectorAll()、querySelector()和matchesSelector()这3种方法,通过CSS选择符查询DOM文档取得元素的引用的功能变成了原生的API,解析和树查询操作在浏览器内部通过编译后的代码来完成,极大地改善了性能。

    与getElementById()方法不同,querySelector()方法得到的对象是静态对象

    与getElementsByTagName()等方法不同,querySelectorAll()方法得到的类数组对象是静态合集。

    querySelector()

    querySelector()方法接收一个CSS选择符,返回与该模式匹配的第一个元素,如果没有找到匹配的元素,返回null。该方法既可用于文档document类型,也可用于元素element类型。

    <body style="height: 100%;">
    <div class="box" id="box" style="height: 200px;">
    <ul class="list" style="height:100px">
            <li class="in" style="height: 30px;">1</li>
            <li class="in" style="height: 30px;" title="test">2</li>
            <li class="in" style="height: 30px;">3</li>
        </ul>    
    </div>
    <script>
        //因为没有.null类名,所以返回null
        var oNull = document.querySelector('.null');
        console.log(oNull); //null
        //通过<body>标签取得元素
        var body = document.querySelector("body");
        console.log(body.style.height); //100%
        //通过id属性取得元素
        var oBox = document.querySelector('#box');
        console.log(oBox.style.height); //200px
        //通过结合元素的类选择器取得元素
        var oList = document.querySelector('ul.list');
        console.log(oList.style.height); //100px
        //通过类名取得元素
        var oIn = document.querySelector('.in');
        console.log(oIn.innerHTML); //1
        //通过属性选择器取得元素
        var oTest = body.querySelector('[title="test"]');
        console.log(oTest.innerHTML); //2
    </script>
    </body> 
    

    querySelectorAll()

    querySelectorAll()接收一个CSS选择符,返回一个类数组对象NodeList的实例。具体来说,返回的值实际上是带有所有属性和方法的NodeList,而其底层实现则类似于一组元素的快照,而非不断对文档进行搜索的动态查询。这样实现可以避免使用NodeList对象通常会引起的大多数性能问题。

    没有匹配元素时,返回空的类数组对象,而不是null

    <body style="height: 100%;">
    <div class="box" id="box" style="height: 200px;">
    <ul class="list" style="height:100px">
            <li class="in" style="height: 30px;">1</li>
            <li class="in" style="height: 30px;" title="test">2</li>
            <li class="in" style="height: 30px;">3</li>
        </ul>    
    </div>
    <script>
        //返回[]
        var oNull = document.querySelectorAll('.null');
        console.log(oNull);
        //取得body元素
        var body = document.querySelectorAll("body")[0];
        console.log(body.style.height); //100%
        //取得所有class为"in"的元素
        var oIn = document.querySelectorAll('.in');
        for (var i = 0; i < oIn.length; i++) {
            console.log(oIn[i].innerHTML); //1,2,3    
        }
        //取得title属性为test的元素
        var oTest = body.querySelectorAll('[title="test"]');
        console.log(oTest); //[li.in]
    </script>
    </body>
    

    缺陷

    selector类方法在元素上调用时,指定的选择器仍然在整个文档中进行匹配,然后过滤出结果集,以便它只包含指定元素的后代元素。它意味着选择器字符串能包含元素的祖先而不仅仅是所匹配的元素

    <div id="container">
        <div>1</div>
        <div>2</div>
    </div>
    <script>
        var container = document.getElementById('container');
        console.log(container.querySelectorAll('div div')); //[div div]
    </script>

    所以,如果出现后代选择器,为了防止该问题,可以在参数中显式地添加当前元素的选择器

    <div id="container">
        <div>1</div>
        <div>2</div>
    </div>
    <script>
        var container = document.getElementById('container');
        console.log(container.querySelectorAll('#container div div')); //[]
        console.log(container.querySelectorAll('#container div')); //[div div]
        console.log(container.querySelectorAll('div')); //[div div]
    </script>
  • 相关阅读:
    js学习笔记7----return,arguments及获取元素样式
    js学习笔记6----作用域及解析机制
    js学习笔记5----函数传参
    js学习笔记4----数据类型
    Flashtext 使用文档 大规模数据清洗的利器-实现文本结构化
    Linux之目录的操作(创建、移动、改名、删除、复制)
    Python 异常处理
    Python 内置模块函数filter reduce
    Python处理文件以及文件夹常用方法
    Python 字符串常用方法
  • 原文地址:https://www.cnblogs.com/MasterYao/p/8743133.html
Copyright © 2020-2023  润新知