沿着树移动

DOM 节点包含了许多指向相邻节点的链接。下面的图表展示了这一点。

沿着树移动 - 图1

尽管图表中每种类型的节点只显示出一条链接,但每个节点都有parentNode属性,指向一个节点,它是这个节点的一部分。类似的,每个元素节点(节点类型为 1)均包含childNodes属性,该属性指向一个类数组对象,用于保存其子节点。

理论上,你可以通过父子之间的链接移动到树中的任何地方。但 JavaScript 也提供了一些更加方便的额外链接。firstChild属性和lastChild属性分别指向第一个子节点和最后一个子节点,若没有子节点则值为null。类似的,previousSiblingnextSibling指向相邻节点,分别指向拥有相同父亲的前一个节点和后一个节点。对于第一个子节点,previousSiblingnull,而最后一个子节点的nextSibling则是null

也存在children属性,它就像childNodes,但只包含元素(类型为 1)子节点,而不包含其他类型的子节点。 当你对文本节点不感兴趣时,这可能很有用。

处理像这样的嵌套数据结构时,递归函数通常很有用。 以下函数在文档中扫描包含给定字符串的文本节点,并在找到一个时返回true

  1. function talksAbout(node, string) {
  2. if (node.nodeType == document.ELEMENT_NODE) {
  3. for (let i = 0; i < node.childNodes.length; i++) {
  4. if (talksAbout(node.childNodes[i], string)) {
  5. return true;
  6. }
  7. }
  8. return false;
  9. } else if (node.nodeType == document.TEXT_NODE) {
  10. return node.nodeValue.indexOf(string) > -1;
  11. }
  12. }
  13. console.log(talksAbout(document.body, "book"));
  14. // → true

因为childNodes不是真正的数组,所以我们不能用for/of来遍历它,并且必须使用普通的for循环遍历索引范围。

文本节点的nodeValue属性保存它所表示的文本字符串。