美文网首页
原生JS模拟出jquery的find()方法(简单递归)

原生JS模拟出jquery的find()方法(简单递归)

作者: DHFE | 来源:发表于2018-07-19 23:46 被阅读1184次

    jQuery中的find()函数可以在给定的父元素中,获得当前父元素下指定的子元素集合。
    关于find()的具体使用就不细说了,重点是如何使用原生JS来实现一样的功能。

    当时想的方法是用递归来完成DOM树的遍历。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <div class="carousel" id="id_carousel">
            <ul class="img-ct">
                <li id="0">
                    <a href="#">
                        <p>p0</p>
                    </a>
                </li>
                <li id="1">
                    <a href="#">
                        <p>p1</p>
                    </a>
                </li>
            </ul>
        </div>
        <script>
            function findRecursion(parent, label) {
                for (var i = 0; i < parent.children.length; i++) {
                    console.log(parent.children[i]);
                    findRecursion(parent.children[i], label);
                }
            }
            /*
            ul.img-ct {compact: false, type: "", title: "", lang: "", translate: true, …}
            li#0 {value: 0, type: "", title: "", lang: "", translate: true, …}
            a {target: "", download: "", ping: "", rel: "", relList: DOMTokenList(0), …}
            p {align: "", title: "", lang: "", translate: true, dir: "", …}
            li#1 {value: 0, type: "", title: "", lang: "", translate: true, …}
            a {target: "", download: "", ping: "", rel: "", relList: DOMTokenList(0), …}
            p {align: "", title: "", lang: "", translate: true, dir: "", …}
            */
        </script>
    </body>
    </html>
    

    其实自己对递归不是很熟练(科班出身学过算法的优势马上体现出来了有没有!),了解也不是很深刻,以至于当时写出来甚至都不知道如何运行的,后面一步一步打断点运行后才了解,也知道了为什么jQuery中find()的源码没有使用这种方法来遍历DOM。

    调试界面
    可以看到在调用堆栈中,有5个findRecursion()函数在堆栈内执行,此时遍历DOM深度是遍历到第一个li元素内的p元素上。由于p本身没有后代元素(children.length=0),不会再继续调用函数递归下去,执行栈弹出函数,i自增......直到碰到下一个children.length>1的元素,继续遍历下去。

    实际上,节点中每存在一个后代节点,就会执行一次函数,如果元素节点很多很深,很容易造成栈溢出。

            <ul class="img-ct">
                <li id="0">
                    <a href="#">
                        <p>p0</p>
                    </a>
                </li>
                <li id="1">
                    <a href="#">
                        <p>p1</p>
                    </a>
                </li>
            </ul>
    

    这是优化了一下函数,简单模拟了find()的功能。加入class、id、tagName参数用于对比,数组用于保存符合功能的元素。

    var result = [];
    function findRecursion(parent,label) {
        for (var i = 0; i < parent.children.length; i++) {
    
            if (([].indexOf.call(parent.children[i].classList,label) !== -1) || parent.children[i].id === label || parent.children[i].tagName === label) {
                result.push(parent.children[i]);
            }
    
            findRecursion(parent.children[i], label);
        }
    }
    
    findRecursion(document.querySelectorAll(".carousel")[0],"P");   // Array(4) [p, p, p, p.p3]
    console.log(result);
    result = [];
    
    findRecursion(document.querySelectorAll(".carousel")[0],"3");   // Array(1) [li#3]
    console.log(result);
    result = [];
    
    findRecursion(document.querySelectorAll(".carousel")[0],"img-ct");   // Array(1) [ul.img-ct]
    console.log(result);
    result = [];
    
    

    测试HTML

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <div class="carousel" id="id_carousel">
            <ul class="img-ct">
                <li id="0">
                    <a href="#"><p>p0</p></a>
                </li>
                <li id="1">
                    <a href="#"><p>p1</p></a>
                </li>
                <li id="2">
                    <a href="#"><p>p2</p></a>
                </li>
                <li id="3">
                    <a href="#"><p class="p3">p3</p></a>
                </li>
            </ul>
        </div>
    </body>
    </html>
    

    当然问题也有很多,如没有使用this,参数类型不严谨,每执行一次result数组要归0等等。

    关于尾递归


    待更

    相关文章

      网友评论

          本文标题:原生JS模拟出jquery的find()方法(简单递归)

          本文链接:https://www.haomeiwen.com/subject/xfogpftx.html