变态的节点集合

今天想实现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是没有的……

你可能感兴趣的:(集合)