由html空格引起的非常奇怪的错误

Yso*_*oL8 5 html javascript debugging

我在Firefox中遇到了一个非常奇怪的错误.

我在外部文件中有一个javascript函数,可以在常规复杂网站上完美运行.然而,我一直在组织一些示例,并遇到一些奇怪的事情.

使用html格式化(在编辑器中):

<div><p>Q: Where's the rabbit?</p><p class="faq_answer">A: I don't know, honest</p></div>
Run Code Online (Sandbox Code Playgroud)

Javascript按预期工作.

但是当这样的时候:

<div>
<p>Q: Where's the rabbit?</p>
<p class="faq_answer">A: I don't know, honest</p>
</div>
Run Code Online (Sandbox Code Playgroud)

它失败了:

elementsList[i].parentNode.firstChild.appendChild(finalRender.cloneNode(true));
Run Code Online (Sandbox Code Playgroud)

为什么在地球上格式化html会导致什么呢?

Fel*_*ing 7

这不是一个bug.DOM不仅有元素节点,还有文本节点 [docs](等等).在这个例子中:

<div>
<p>Q: Where's the rabbit?</p>
Run Code Online (Sandbox Code Playgroud)

你至少有两个文本节点:

  • 一个在<div>和之间<p>,包含一个换行符.
  • <p>元素节点内的一个文本节点,包含文本Where's the rabbit?.

因此,如果elementsList[i].parentNode指的是<div>元素,

elementsList[i].parentNode.firstChild
Run Code Online (Sandbox Code Playgroud)

将引用第一个文本节点.

如果要获取第一个元素节点,请使用

elementsList[i].parentNode.children[0]
Run Code Online (Sandbox Code Playgroud)

更新:您提到了Firefox 3.0,实际上,此版本不支持children属性.

Afaik唯一的解决方案是遍历子节点(或遍历它们)并测试它是否是文本节点:

var firstChild = elementsList[i].parentNode.firstChild;

// a somehow shorthand loop
while(firstChild.nodeType !== 1 && (firstChild = firstChild.nextSibling));

if(firstChild) {
    // exists and found
}
Run Code Online (Sandbox Code Playgroud)

你可能想把它放在一个额外的功能:

function getFirstElementChild(element) {
    var firstChild = null;
    if(element.children) {
        firstChild = element.children[0] || null;
    }
    else {
      firstChild = element.firstChild;
      while(firstChild.nodeType !== 1 && (firstChild = firstChild.nextSibling));
    }
    return firstChild;
}
Run Code Online (Sandbox Code Playgroud)

您可以(也应该)考虑使用从所有这些中抽象出来的库,比如jQuery.

这取决于你的代码实际在做什么,但如果你为每个节点运行这个方法,它将是这样的:

$('.faq_answer').prev().append(finalRender.cloneNode(true));
Run Code Online (Sandbox Code Playgroud)

(假设p元素总是在.faq_answer元素之前)

这是整个代码,您不必再循环遍历元素.