$("#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遍历会导致性能问题,所以递归调用的方法可能会存在效率上的问题。所以各自权衡吧~
随机推荐
- Microsoft SqlServer2008技术内幕:T-Sql语言基础-读书笔记1
一.理论背景:关系模型,其数学理论是集合论和谓词逻辑. 1.集合论:集合定义是把我们直观或思维中确定的,相互间有明确区别的那些对象视为一个整体,这个整体就是集合. 2.谓词逻辑:谓词是判断对象是否有某 ...
- Oracle redo 日志切换时间频率
DB: 11.2.0.3.0 查看Oracle的redo日志切换频率 两条SQL,原理是一样的,第二个用到了统计函数 时间单位:分钟 方法一. select * from v$log a where ...
- android开发系列之代码整洁之道
说起代码整洁之道,想必大家想到更多的是那本经典重构书籍.没错,记得当时自己读那本书的时候,一边结合项目实战,一边结合书中的讲解,确实学到了很多东西,对我自己的编码风格影响极深.随着时间的流逝,书中很多 ...
- angularJS项目-ajax事件的按钮loading和页面loading状态 & Controller之间通信-待续
1).按钮loading --TODO 2). page loading状态 1.在module中注入指令 // Route State Load Spinner(used on page or co ...
- iOS 进阶 第十八天(0423)
0423 - GCD( Grand Central Dispatch) block复习 请问,图中输出结果是多少?为什么? 答:结果是10.因为在定义block的时候,block会把它前面的要用到的变 ...
- ubuntu 修改主机名
sudo gedit /etc/hostname sudo gedit /etc/hosts
- 替换APK中的jar包文件
[Qboy] 2014年12月21日 这几天,我第一次做的android游戏(WE!青春纪)马上就要上线.上线之前需要把各个渠道的SDK加入到我们游戏中,与渠道进行联运.但是商务很给力,一下子联系了1 ...
- Leetcode Variant-Plus N
Given a non-negative number represented as an array of digits, plus N to the number. The digits are ...
- [Z] 深入浅出 Systemd
1. Systemd 的简介和特点 Systemd 是 Linux 系统中最新的初始化系统(init),它主要的设计目标是克服 sysvinit 固有的缺点,提高系统的启动速度.systemd 和 u ...
- PyDev for Eclipse 简介
PyDev 安装和配置 安装 PyDev 在安装 PyDev 之前,要保证您已经安装了 Java 1.4 或更高版本.Eclipse 以及 Python.接下来,开始安装 PyDev 插件. 启动 E ...