題外話:這問題遇到好多遍,每次都不記得怎麼解決,這次寫下來好好提醒自己。
一、問題的出現
在寫原生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;
(或者是檢測節點的類型)
這樣便跳過這些多餘的節點,使程式啟動並執行更有效率。