Ruby's Louvre

每天学习一点点算法

导航

变态的节点集合

今天想实现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>

如果预先将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)
      }

很显然nodeList还一些奇怪的特性是数组没有的。从运行框2中,我们可以看到把节点appendChild到文档碎片时,其实会把它从DOM树中剥离出来,nodeList一定是跟踪这变化,动态改变了它自身,而直线递加的i是无法对应正确的节点的索引!因此我们每次取得它的firstChild就行了。

      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)
      }

顺便一提,由getElementsByTagName取得的HTMLCollection也是这个样子,因此处理这类节点集合要打起十二分精神了!

这两种节点集合在各浏览器还实现得不太一样,如标准浏览器我们可以用Array.prototype.slice.call将它们转换为原生数组,IE则报错。标准浏览器的它们有hasOwnProperty与valueOf,而IE是没有的……

posted on 2010-03-19 15:49  司徒正美  阅读(1893)  评论(1编辑  收藏  举报