日期:2014-05-16  浏览次数:20305 次

insertBefore与insertAfter
JavaScript DOM编程艺术
我最近看这个,看到动态创建html;介绍的insertBefore函数,没有insertAfter函数,然后作者便自己创建一个insertAfter函数,代码如下
function insertAfter(newElement,targetElement) {
  var parent = targetElement.parentNode;
  if (parent.lastChild == targetElement) {
    parent.appendChild(newElement);
  } else {
    parent.insertBefore(newElement,targetElement.nextSibling);
  }
}
我的问题在这个lastChild上
比如:
<body>
 <p id="test">xxx</p>
</body>
var pObj=document.getElementById("test");
然后我创建一个元素对象A,要插在pObj后
insertAfter(A,pObj);
pObj.parentNode是body,body的lastChild应该是文本节点xxx才对。也就是说对象A应该插在元素节点与文本节点之间。但是书中效果又不是这样的。有没有人看过这个函数,怎么理解的?



------解决方案--------------------
p是一个元素 p里边的xxx是p的childNodes
所以lastChid是p元素 或者p后边的空白文本(和浏览器有关)
lastChild只会计算子节点  不会计算后代节点的 
------解决方案--------------------
lastChild说的是child,不是grandson,所以不会是XXX的,XXX是孙子辈的了。


不过,分析看来,如果源码换行了,(body的>和p的<没有直接接上,而是出现换行或空格),那么实际中间有一个textNode节点的。也就是说body其实有3个子节点,
 body
 ├─textNode
 ├─p
 │   └─textNode(nodeValue=XXX)
 └─textNode

因此,p不是body的lastChild,最后那个textNode才是!
然而一般空的textNode对我们根本没有意义,现代浏览器引入了lastElementChild。在没有这个属性的浏览器上,只能通过previousSibling然后判断nodeType逐一来排除textNode了找到我们要的Element。

类似的有firstChild,previousSibling,nextSibling,在现代浏览器中都有其Element版本。