今天想實現jQuery的unwrap效果,換言之,就是用其孩子把其父節點幹掉。為了效率,用到文檔片段,而取孩子時使用到childNodes(返回一個nodeList)
<!doctype html><html lang="en"> <head> <meta charset="utf-8" /> <meta content="IE=8" http-equiv="X-UA-Compatible"/> <title>節點集合 by 司徒正美 </title> <style> #aaa { padding:10px; border:1px solid red; } p { border:1px solid blue; } </style> <script type="text/javascript"> window.onload = function(){ var d = document.createDocumentFragment(); var div = document.getElementById("aaa"); var c = div.childNodes; for(var i=0,n=c.length;i<n;i++){ alert(c[i] + " "+ i) d.appendChild(c[i]) } div.parentNode.replaceChild(d,div) } </script> </head> <body> <div id="aaa"> <p class="aaaa">司徒正美</p> <p class="aaaa">司徒正美</p> <p class="aaaa">司徒正美</p> <p class="aaaa">司徒正美</p> <p class="aaaa">司徒正美</p> </div> </body></html>
<br /><!doctype html><br /><html lang="en"><br /> <head><br /> <meta charset="utf-8" /><br /> <meta content="IE=8" http-equiv="X-UA-Compatible"/><br /> <title>節點集合 by 司徒正美 </title><br /> <style><br /> #aaa {<br /> padding:10px;<br /> border:1px solid red;<br /> }<br /> p {<br /> border:1px solid blue;<br /> }<br /> </style><br /> <script type="text/javascript"><br /> window.onload = function(){<br /> var d = document.createDocumentFragment();<br /> var div = document.getElementById("aaa");<br /> var c = div.childNodes;<br /> for(var i=0,n=c.length;i<n;i++){<br /> alert(c[i] + " "+ i)<br /> d.appendChild(c[i])<br /> }<br /> div.parentNode.replaceChild(d,div)<br /> }<br /> </script></p><p> </head><br /> <body></p><p> <div id="aaa"><br /> <p class="aaaa">司徒正美</p><br /> <p class="aaaa">司徒正美</p><br /> <p class="aaaa">司徒正美</p><br /> <p class="aaaa">司徒正美</p><br /> <p class="aaaa">司徒正美</p><br /> </div><br /> </body><br /></html><br />
運行代碼
如果預先將nodeList轉換為數組就沒有問題!
window.onload = function(){ var d = document.createDocumentFragment(); var div = document.getElementById("aaa"); var c = div.childNodes; var arr = []; for(var i=0,n=c.length;i<n;i++){ arr.push(c[i]) } for(var i=0,n=arr.length;i<n;i++){ alert(arr[i] + " "+ i) d.appendChild(arr[i]) } div.parentNode.replaceChild(d,div) }
<br /><!doctype html><br /><html lang="en"><br /> <head><br /> <meta charset="utf-8" /><br /> <meta content="IE=8" http-equiv="X-UA-Compatible"/><br /> <title>節點集合 by 司徒正美 </title><br /> <style><br /> #aaa {<br /> padding:10px;<br /> border:1px solid red;<br /> }<br /> p {<br /> border:1px solid blue;<br /> }</p><p> </style><br /> <script type="text/javascript"><br /> window.onload = function(){<br /> var d = document.createDocumentFragment();<br /> var div = document.getElementById("aaa");<br /> var c = div.childNodes;<br /> var arr = [];<br /> for(var i=0,n=c.length;i<n arr.push for i="0,n=arr.length;i<n;i++){" alert d.appendchild div.parentnode.replacechild id="aaa" class="aaaa"><p><button type="button" class="runcode" title="runcode2">運行代碼</button></p><p>很顯然nodeList還一些奇怪的特性是數組沒有的。從運行框2中,我們可以看到把節點appendChild到文檔片段時,其實會把它從DOM樹中剝離出來,nodeList一定是跟蹤這變化,動態改變了它自身,而直線遞加的i是無法對應正確的節點的索引!因此我們每次取得它的firstChild就行了。</p><pre class="brush:javascript;gutter:false;toolbar:false;"> window.onload = function(){ var d = document.createDocumentFragment(); var div = document.getElementById("aaa"); var c = div.childNodes; while(c.length) d.appendChild(c[0])//每次只取它第一個節點,直到取空 div.parentNode.replaceChild(d,div) }</pre><p><textarea id="runcode3" style="width:75%" rows="10"><br /><!doctype html><br /><html lang="en"><br /> <head><br /> <meta charset="utf-8" /><br /> <meta content="IE=8" http-equiv="X-UA-Compatible"/><br /> <title>變態的childNodes by 司徒正美 </title><br /> <style><br /> #aaa {<br /> padding:10px;<br /> border:1px solid red;<br /> }<br /> p {<br /> border:1px solid blue;<br /> }</p><p> </style><br /> <script type="text/javascript"><br /> window.onload = function(){<br /> var d = document.createDocumentFragment();<br /> var div = document.getElementById("aaa");<br /> var c = div.childNodes;<br /> while(c.length) d.appendChild(c[0])//每次只取它第一個節點,直到取空<br /> div.parentNode.replaceChild(d,div)<br /> }<br /> </script></p><p> </head><br /> <body></p><p> <div id="aaa"><br /> <p class="aaaa">司徒正美</p><br /> <p class="aaaa">司徒正美</p><br /> <p class="aaaa">司徒正美</p><br /> <p class="aaaa">司徒正美</p><br /> <p class="aaaa">司徒正美</p><br /> </div><br /> </body><br /></html><br />
運行代碼
順便一提,由getElementsByTagName取得的HTMLCollection也是這個樣子,因此處理這類節點集合要打起十二分精神了!
<br /><!doctype html><br /><html lang="en"><br /> <head><br /> <meta charset="utf-8" /><br /> <meta content="IE=8" http-equiv="X-UA-Compatible"/><br /> <title>HTMLCollection by 司徒正美 </title><br /> <style><br /> #aaa {<br /> padding:10px;<br /> border:1px solid red;<br /> }<br /> p {<br /> border:1px solid blue;<br /> }</p><p> </style><br /> <script type="text/javascript"><br /> window.onload = function(){<br /> var d = document.createDocumentFragment();<br /> var div = document.getElementById("aaa");<br /> var c = document.getElementsByTagName("p")<br /> for(var i=0,n=c.length;i<n;i++){<br /> alert(c[i] + " "+ i)<br /> d.appendChild(c[i])<br /> }<br /> div.parentNode.replaceChild(d,div)<br /> }<br /> </script></p><p> </head><br /> <body></p><p> <div id="aaa"><br /> <p class="aaaa">司徒正美</p><br /> <p class="aaaa">司徒正美</p><br /> <p class="aaaa">司徒正美</p><br /> <p class="aaaa">司徒正美</p><br /> <p class="aaaa">司徒正美</p><br /> </div><br /> </body><br /></html><br />
運行代碼
這兩種節點集合在各瀏覽器還實現得不太一樣,如標準瀏覽器我們可以用Array.prototype.slice.call將它們轉換為原生數組,IE則報錯。標準瀏覽器的它們有hasOwnProperty與valueOf,而IE是沒有的……