You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript递归统计DOM节点 文本/空白/总节点计数少1问题

问题描述

开发JavaScript课程项目时,通过递归函数遍历页面article元素内所有节点构建节点树,调用makeBranches函数统计总节点数、元素节点、文本节点、空白节点数量,最终将结果渲染到页面指定段落。运行代码后仅元素节点计数正确,总节点、文本节点、空白节点的统计值均比预期值少1。
预期正确统计结果:

  • 总节点:238个
  • 元素节点:98个
  • 文本节点:140个
  • 空白节点:57个
    实际运行时除元素节点外,其余三类计数均比预期少1。
问题原因
  1. 脚本加载时机问题:你在head中引入脚本时添加了async属性,该属性会让浏览器并行下载脚本、不阻塞DOM解析,但脚本下载完成后会立即执行,执行顺序不受保证。虽然绑定了window.onload事件触发统计函数,但在部分浏览器内核实现中,若async脚本下载耗时极短,会在DOM树收尾解析阶段(即</article>标签前的最后一个空白文本节点被加入DOM树前)就完成事件绑定,等到onload触发时,统计逻辑会漏掉这个根容器末尾的空白文本节点,最终导致总节点、文本节点、空白节点计数各少1;而元素节点解析优先级更高,已经全部加入DOM树,因此计数保持正确。
  2. HTML标签笔误问题:你提供的代码中表格内nextSibling对应的代码标签存在闭合错误:<td><code><em>node</em>.nextSibling</code</td>,</code缺少闭合尖括号>,浏览器自动修正DOM结构时可能出现节点解析偏差,也会导致计数异常。
修复方案

可按以下步骤修复,选择对应方案即可:

  1. 修正脚本加载配置:移除脚本标签的async属性,要么使用默认同步加载,要么添加defer属性保证脚本在DOM完全解析完成后再执行:
    <!-- 方案1:移除async,默认同步加载 -->
    <script src="js_tree.js"></script>
    
    <!-- 方案2:使用defer属性,DOM解析完成后执行脚本 -->
    <script src="js_tree.js" defer></script>
    
    也可以直接将脚本标签移动到</body>标签前引入,此时DOM树已经完全解析完成,不会出现节点漏统计问题。
  2. 修正HTML笔误:补全未闭合的code标签,避免浏览器解析异常:
    <td><code><em>node</em>.nextSibling</code></td>
    
  3. 优化计数逻辑(可选):在统计函数执行前显式重置全局计数变量,避免页面热更新、脚本重复执行时出现计数累加问题:
    function makeTree() {
      // 每次执行前重置计数
      nodeCount = 0;
      elemCount = 0;
      textCount = 0;
      wsCount = 0;
    
      var nodeList = document.createElement("ol");
      var sourceArticle = document.querySelector("#main article");
      makeBranches(sourceArticle, nodeList);
    
      // 原有渲染逻辑保持不变
      document.getElementById("totalNodes").innerHTML = nodeCount;
      document.getElementById("elemNodes").innerHTML = elemCount;
      document.getElementById("textNodes").innerHTML = textCount;
      document.getElementById("wsNodes").innerHTML = wsCount;
    }
    

内容的提问来源于stack exchange,提问作者Matthew Wheeler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 19:27:22