$("#id a") - $("#id .c a") = ?

前沿

这是之前淘宝的一道面试题,题目借用了 jQuery 选择器的语法。大概的意思是,从 #id 元素内选出所有不是 .c 后代的 a 元素,即父元素 #id 内的所有后代元素中,选出不是 .c 后代元素里的所有a元素。题目主要考察的是 DOM 操作的知识,来筛选DOM元素,并且不能使用jQuery等框架。

 

思路

先选出所有 a 元素。对每个 a 元素,从其所在位置沿着 DOM 树往上搜索,每走一步对比当前节点类名,含有 c 类立刻中止,否则继续上行直至根节点或父元素(#id)处,结束搜索并将 a 元素加入结果集里。对全部 a 元素执行完该操作后,返回结果集。

查找过程的流程图如下:

 

js核心代码:

// 参数依次为根元素、给出的类名、目标元素(即一一对应题目中的$("#id .c a"))
        var  domSelector = function(rootId, filterClass, targetTag) {
            var root = document.getElementById(rootId),
                nodes = root.getElementsByTagName(targetTag),
                resultArr = [],
                i,
                len;
             
             // 沿着DOM树查找
            var ascend = function(start, end, current) {
                if(current === end) { // 查找成功
                    resultArr.push(start);
                // 没查找到则继续沿着DOM树往上搜索(递归调用)
                } else if((" " + current.className.toLowerCase() + " ").indexOf(" " + filterClass + " ") == -1) { 
                    ascend(start, end, current.parentNode);
                }
            };
         
            for (i = 0, len = nodes.length; i < len; i++) {
                ascend(nodes[i], root, nodes[i].parentNode); // 循环便利
            }
         
            return resultArr;
        };

 

测试:

HTML结构:

    <div id="id">
        <div>
            <a href="" class="A1">A1</a>
        </div>
        <div class="c">
            <a href="" class="A2">A2</a>
        </div>
        <div class="d">
            <a href="" class="A3">A3</a>
        </div>
    </div>    

调用函数:

        // 测试
        window.onload = function() {
            // 调用函数
            var res = domSelector("id", "c", "a");
            console.log(res); // 返回一个数组:[a.A1, a.A3]
        };        

 

结语

由于过多的DOM遍历会导致性能问题,所以递归调用的方法可能会存在效率上的问题。所以各自权衡吧~

 

 

posted @ 2013-09-28 10:45  chmyun  阅读(734)  评论(2编辑  收藏  举报