意外的childNodes行为

时间:2012-12-18 20:41:49

标签: javascript html dom dom-traversal textnode

我设置了一些简单的HTML和JS代码,以便更好地处理遍历DOM。

这是我的HTML:

<!DOCTYPE html>
<html>
  <head>
    <title>Sandbox</title>
  </head>
  <body>
    <div>
      <h1 id="title">Sandbox</h1>
      <button id="clickMe" onclick="playingAroundWithNodes()">Play with nodes!</button>
    </div>
  </body>
  <script type="text/javascript" src="Sandbox3.js"></script>
</html>

这是我的JavaScript:

function playingAroundWithNodes() {

    //Getting a reference to some nodes!

    var theHtmlNode = document.childNodes[1];
    var theHeadNode = theHtmlNode.childNodes[0];
    var theBodyNode = theHtmlNode.childNodes[1];

    //Let's check out those nodes!

    console.log("theHtmlNode is a " + theHtmlNode.nodeName + " type node.");
    console.log("theHeadNode is a " + theHeadNode.nodeName + " type node.");
    console.log("theBodyNode is a " + theBodyNode.nodeName + " type node.");

}

这是我得到的控制台日志:

theHtmlNode is a HTML type node.
theHeadNode is a HEAD type node. 
theBodyNode is a #text type node. 

是什么给出的?那就是那个文本节点,那不是标题节点吗?我很困惑,并且已经玩了很多(并且根据js发现身体节点实际上是HEAD的第3个孩子,但是看着对我来说没有意义的HTML)。我可以看到它是第三个后代或什么的,但我认为孩子意味着直接的孩子...任何帮助赞赏!

3 个答案:

答案 0 :(得分:2)

首先,你认为我有新的东西。我没有意识到document有一个childNodes属性(通常是通过document.documentElement访问根元素(html))。

对于文本节点,这些将取决于您格式化HTML文件的方式。上面提到的文本节点可能是返回字符或结束</head>和开始<body>之间的几个空格。

您可能正在寻找的是(最初是非标准但现在最近proposed for standardisationelement.childrenJohn Resig has a good overview

因此,如果您按照以下方式修改上述代码,您将得到您期望的结果:

var theHeadNode = theHtmlNode.children[0];
var theBodyNode = theHtmlNode.children[1];

答案 1 :(得分:1)

IE是唯一能够按预期运行的浏览器。所有其他浏览器都实现了标准,标准说空白也必须是DOM的一部分。

因此,对于看起来像这样的HTML:

<html>
    <body>
        <div>Hello</div>
    </body>
</html>

IE将创建此DOM:

html +
     |____ body +
                |____ div +
                          |____ text("Hello")

但是所有其他浏览器都会创建这个DOM

html +
     |____ text("\n    ")
     |
     |____ body +
     |          |____ text("\n        ")
     |          |
     |          |____ div +
     |          |         |____ text("Hello")
     |          |
     |          |____ text("\n        ")
     |
     |____ text("\n    ")

我不确定你是如何获得结果的,因为在<html>之前和之后应该有文本节点。

无论如何,答案是因为标准要求它。因此,不要盲目地使用硬编码索引来遍历childNodes,因为像minifiers这样的东西可能会因空白而改变DOM。循环遍历所有子节点并在找到所需节点后停止或使用getElementsByTagName。

答案 2 :(得分:0)

@mcabrams:除了@slebatman提到的内容,如果你想直接访问正文名称,只需使用:

var bodyNode = document.body;  //it returns a refrence to the body node

希望有所帮助。