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