题外话:这问题遇到好多遍,每次都不记得怎么解决,这次写下来好好提醒自己。
一、问题的出现
在写原生Javascript时,我们会经常使用getElementsByTagName()和childNodes来实现对节点的遍历,但是getElementsByTagName()对复杂的DOM结构遍历明显不如用childNodes,因为childNodes能更好的处理DOM的层次结构。
但是在跨浏览器开发中,问题就出现了:
<html> <head></head> <body onload="check();"> <!--第一个要遍历的div,节点之间留有空格和回车--> <div id="firDiv"> <div>1</div> <div>2</div> <div>3</div> </div> <!--第二个要遍历的div,节点间无空格回车--> <div id="secDiv"><div>first</div><div>second</div><div>third</div></div> <script type="text/javascript"> function check(){ var childs1=$('firDiv').childNodes; var childs2=$('secDiv').childNodes; alert("length of First Div: "+childs1.length+" , length of Second Div: "+childs2.length); } var $=function(id){ return document.getElementById(id); } </script> </body> </html>
亲测后发现,用IE运行的结果是是3,3,而用Firefox、Chrome、Safari和Opera运行的结果则是7,3。
咦,怎么会有这种情况?
二、问题的根源
在结构上,div1和div2不同的地方在于,div1的子节点间有回车或者空格,而对象2则是一行写到尾。
造成不一致的原因就在于这:
IE是将一个完整标签作为一个节点。
而Firefox等浏览器除了上述的的情况外,也把一个标签的结束符“>”到下一个标签的起始符“<”之间的内容(除注释外,包括任何的文字、空格、回车、制表符)也算是一个节点,而且这种节点也有它们自己独特的属性和值:nodeName="#text"。
三、解决方法
在非IE内核的浏览器上使用childNodes遍历子节点时,将这些多余的节点过滤掉即可。
比如在for循环里加上:
if(childNode.nodeName=="#text") continue;
(或者是检测节点的类型)
这样便跳过这些多余的节点,使程序运行的更有效率。