非递归遍历 DOM 结构
上次在Google+ 上说 实现了非递归遍历 DOM 结构,
有朋友想让分享,我当然很高兴,但是很遗憾这本身没有什么值得分享的,大致如下,
给大家随便看一下:
常见的递归方式遍历方式,下面是 Douglas Crockford 写的递归实现:
1function walkTheDOM (node, func) {
2 func(node);
3 node = node.firstChild;
4 while (node) {
5 walkTheDOM(node, func);
6 node = node.nextSibling;
7 }
8}
然后有人自称写出了更快的遍历 DOM 方式。
1var elems = document.getElementsByTagName("*");
2for(var i=0,l=elems.length; i<l; i++){
3 handler(elems[i]);
4}
最初找到有详细对照的文章地址没有找到,这个是
类似的一篇,
而且也是非递归式的。
确实是很快的,但只是快还是不够的,这个实现有很多弊端:
- 注释等元素未必会被遍历。
- 树形数据结构被整理成了平板结构,无法实现遍历过程的 in/out 处理。
然后今天的主角隆重登场:
1function walk(node, enter, leave){
2 var tmp, n=node;
3 label:
4 do{
5 enter(n);
6 if(tmp = firstNode(node)){ // firstChild(HTMLElement)
7 n = tmp;
8 }else if(tmp = nextNode(n)){ // nextSibling(HTMLElement)
9 n = tmp;
10 }else if(n.parentNode){
11 do{
12 n = n.parentNode;
13 leave(n);
14 if(n == node){break label;}
15 if(tmp = nextNode(n)){
16 n = tmp;
17 continue label;
18 }
19 }while(node);
20 }else{
21 break;
22 }
23 }while(n && n!=node);
24}
上面只是一个精简版,实际过程中还需要考虑节点类型的问题,一般会过滤
1:HTMLElement, 8:Comment, 9:Document Type, 10:DocType 之外的节点。
其实也不过如此嘛,飘过~~
See Also
Tags: JavaScript, 算法
Published on 2011-07-10