《Eloquent JavaScript》第14章递归函数异常返回问题求助
问题原因与解决方案
问题根源
你的script标签写在了</html>标签之后,浏览器会自动将这个脚本元素纳入document.body的子节点列表中。而脚本代码里明确包含字符串"book"(比如console.log(talksAbout(document.body, "book"));这一行),当递归函数遍历到script元素的文本子节点时,会检测到这个"book",因此函数返回true。
解决方案
方案1:调整脚本位置
将script标签移动到<head>标签内部,这样document.body的子节点就不会包含该脚本,函数只会遍历页面的可见内容:
<!doctype html> <html> <head> <title>My home page</title> <script> function talksAbout(node, string) { if (node.nodeType == Node.ELEMENT_NODE) { for (let child of node.childNodes) { if (talksAbout(child, string)) { return true; } } return false; } else if (node.nodeType == Node.TEXT_NODE) { return node.nodeValue.indexOf(string) > -1; } } // 页面加载完成后再执行,避免找不到document.body window.onload = function() { console.log(talksAbout(document.body, "book")); }; </script> </head> <body> <h1>My home page</h1> <p>Hello, I am Marijn and this is my home page.</p> <p>I also wrote a ! Read it <a href="http://eloquentjavascript.net">here</a>.</p> </body> </html>
方案2:修改函数跳过script标签
在递归函数中添加判断,遇到script元素时直接返回false,不遍历其内容:
function talksAbout(node, string) { if (node.nodeType == Node.ELEMENT_NODE) { // 跳过script标签,避免检测脚本内容 if (node.tagName.toLowerCase() === 'script') return false; for (let child of node.childNodes) { if (talksAbout(child, string)) { return true; } } return false; } else if (node.nodeType == Node.TEXT_NODE) { return node.nodeValue.indexOf(string) > -1; } // 处理其他未知节点类型,默认返回false return false; }
额外优化
原函数缺少对非元素、非文本节点的返回值处理,虽然这不是当前问题的直接原因,但补充return false可以避免潜在的逻辑漏洞。
内容的提问来源于stack exchange,提问作者feinNotiz
相关产品推荐
相关产品推荐

