偶遇两道 JavaScript 题目,觉得都比较有趣,分享一下。
第一道是很老的题目了,getElementsByClassName,写一下当作练习:
下面这个思路比较简单,基本也是 Robert Nyman 的思路了,判断了 IE5 中使用原生的 all 属性代替其不支持的 getElementsByTagName ,使用 indexOf 判断相应的 class 是否匹配。
function getElementsByClassName(className, context, tag){ context = context || document; tag = tag || '*'; var el = ( tag === '*' && context.all) ? context.all : context.getElementsByTagName(tag); // 兼容 IE5 var resultElements = []; var oElement; for( var i = 0; i < el.length; i++ ){ oElement = el[i]; if( oElement.className.indexOf(className) != -1 ) resultElements.push(oElement); } return resultElements; }
在 Chrome 下,匹配 10003 个 class 为 "c" 的 div ,历时 5-8 ms ,IE 7 下历时 40-47 ms 。
要不来个正则作匹配?
function getElementsByClassName(className, context, tag){ context = context || document; tag = tag || '*'; var el = ( tag === '*' && context.all) ? context.all : context.getElementsByTagName(tag); var resultElements = []; className = className.replace(/\-/g, "\\-"); // 转义 className var oRegExp = new RegExp('(^|\\s)' + className + '(\\s|$)'); var oElement; for( var i = 0; i < el.length; i++ ){ oElement = el[i]; if( oRegExp.test(oElement.className) ){ resultElements.push(oElement); } } return resultElements; }
原理跟上面是一样的,但是匹配 class 部分改为用正则表达式,同样是匹配 10003 个 class 为 "c" 的 div ,在 Chrome 下历时 6-9 ms ,在 IE 7 下历时 46-50 ms 。看来,高端的正则在这里并不如期待那样奏效,还是选用第一种方法吧。
不过,Chrome , Firefox 等现代浏览器都有原生的 getElementsByClassName 方法,而且速度完全不是上面的方法能比拟的,所以在第一种方法的基础上调整一下,判断若是能使用原生方法则使用原生的方法:
function getElementsByClassName(className, context, tag){ if( document.getElementsByClassName ){ return document.getElementsByClassName(className); } else { context = context || document; tag = tag || '*'; var el = ( tag === '*' && context.all) ? context.all : context.getElementsByTagName(tag); var resultElements = []; var oElement; for( var i = 0; i < el.length; i++ ){ oElement = el[i]; if( oElement.className.indexOf(className) != -1 ){ resultElements.push(oElement); } } return resultElements; } }
仍是匹配 10003 个 class 为 "c" 的 div ,在 Chrome 下历时 1 ms ,在 IE 下由于 IE 并不支持原生方法,所以仍是 40-47 ms 。另外测试了匹配 50003 个 class 为 "c" 的 div ,在 Chrome 下只需 3 ms (原生方法就是霸气)。
第二道题目是网上看到的淘宝的一道面试题,从 #id 元素内选出所有不是 .c 后代的 a 元素。思路是找到所有 a 元素,逐层遍历其父级元素,判断其 class 是否包含 c ,若有包含则中止本次判断,否则遍历至 #id 元素则通过判断并加入结果集,具体代码如下:
function getElementNotInClass(tag, filterClass, context){ var context = document.getElementById(context) || document.body, nodes = context.getElementsByTagName(tag), resultElements = [], current, i; again: for(i = 0, l = nodes.length; i < l; i++){ current = nodes[i].parentNode; while( current != context ){ if( current.className.indexOf(filterClass) == -1 ) current = current.parentNode; else continue again; } resultElements.push(nodes[i]); } return resultElements; }
本文由 Kayo Lee 发表,本文链接:https://kayosite.com/two-javascript-subjects.html
评论列表
第二题没看懂路过~
@ilikecss 第二题我的思路是把所有的标签放到集合里,再逐个递归其父结点判断类名是否有指定的c类名
个人感觉第一道题的解法应该有点问题,比如说要查询的 taba.a,但是 taba下有两种 .a 和 .ab,似乎 indexOf 就会有问题~感觉把 class 属性的内容 split 之后循环比对可能会更好点,或者说用正则?
@MurphyL 嗯,同意你的意见,不过 split 之后再循环效率会比较低,可以在 用 indexOf 判断时判断两边是否有空格,待会更新一下文章再一起研究!
@Kayo split 应该还好,感觉应该可以在indexOf的className之后拼上一个空格。
端午节了 快更新 快更新吧
@刘荣焕 最近在学习新的东东,过几天有点心得了就会发文章了,习惯了有心得才写博客,所以只能慢慢来了
我是不会做了。。。坐下休息片刻
@zwwooooo 大叔你是不用做了,慢慢坐,莫急
我是来打酱油的~
@野蛮人 欢迎打酱油
Kayo!!好久沒來了,還是看不懂XD
最近好嗎好嗎?這次下定決心一週至少要更新一次,希望能達成目標
@班森 最近乃是各种忙啊,博客都长草了,一个月都没有更新了!
看了好有深度的,还是来学习一下
ie8 以上支持 Document.querySelectorAll, 这个速度很快
@牧风 精益求精呢!
@牧风 貌似你那边的文章打不开了?
@Kayo 貌似主鸡爆了
这么久了,不知博主还在否
第二题我的思路是找两集合,一是所有a all,二是.c下所有a ca
然后遍历all,判断元素是否在ca集合中,如果不在ca中,就是题目所要求的a。