首页 > 解决方案 > Eloquent Javascript 帮助新手

问题描述

在这个例子中,我很难弄清楚递归函数是如何完成的。问题是他在本书后面使用了这种技术,我觉得我需要了解他在做什么,否则我注定要失败。我试图通过控制台记录函数的结果(引号中的部分)以查看它是如何改变的,但它并没有让我清楚地了解正在发生的事情。由于返回经常退出函数和循环,并且函数最后返回 true,我似乎无法追踪函数的工作原理,更不用说递归部分了

function talksAbout(node, string) {
  if (node.nodeType == Node.ELEMENT_NODE) {
    for (let child of node.childNodes) {
       console.log(talksAbout(child,string));
      if (talksAbout(child, string)) {
        return true;
      }
    }
    return false;
  } else if (node.nodeType == Node.TEXT_NODE) {
    return node.nodeValue.indexOf(string) > -1;
  }
}

console.log(talksAbout(document.body, "book"));
// → true

标签: javascriptdom

解决方案


根据我对此的最佳理解,假设代码块是talkAbout 函数,这是它的工作原理。

if (node.nodeType == Node.ELEMENT_NODE) {

我猜这是在检查它正在查看的节点是否是可能包含其他节点的“元素”。

    for (let child of node.childNodes) {
       console.log(talksAbout(child,string));
      if (talksAbout(child, string)) {
        return true;
      }
    }
    return false;

在这里,函数似乎在遍历元素的子元素。我能解释的最好的是,它基本上是在一个元素的树下发送一个自身的“链”,如果它找到它正在寻找的东西,它会返回 true。如果它没有找到任何东西,则返回 false。

  } else if (node.nodeType == node.text_NODE) {

这是检查它正在查看的节点是否是文本节点,我假设它可能没有任何其他子节点。

     return node.nodeValue.indexOf(string) > -1;
  }

在这里,它正在检查“string”参数中的字符串是否存在于节点内。如果是,则返回 true,并且此“true”沿递归调用行级联,最终,整个函数返回 true。

如果不是,它只是有点......什么都不做,让“链”中的其他调用检查其他内容。

编辑:

事实证明,该功能过于复杂。不必使用递归函数来搜索所有子项:可以只搜索node.textContent并检查您要查找的字符串。递归函数等价于这个简化函数:

function talksAbout(node, string) {
   return node.textContent.indexOf(string) > -1;
}

还应该注意的是,如果<script>包含函数调用的标签在被搜索的节点内,则该函数将始终返回true,因为它会到达脚本标签并找到函数的“字符串”参数。

例子:

function talksAbout(node,string) {
  return node.textContent.indexOf(string) > -1; // functionally equivalent to the recursive function
}
console.log("document.body talks about 'book': " + talksAbout(document.body, "book")); // This script tag is inside document.body, so it finds the "book" string here
console.log("wrapper talks about 'bar': " + talksAbout(document.getElementById("wrapper"), "bar")); // finds string in second layer
console.log("example talks about 'bar': " + talksAbout(document.getElementById("example"), "bar")); // the word "bar" comes before the element being searched
<div id="wrapper">foo
  <div>bar
    <div id="example">baz</div>
  </div>
</div>


推荐阅读