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

递归删除对象数组内嵌套目标节点时为何出现最大调用栈超限报错

栈溢出根因定位

原实现的无限递归是函数逻辑和调用方式完全错位导致的:

  • 递归调用时传入的entry.children、currentId两个实参,根本没有被原_worktreeItemDelete函数接收——该函数的定义只预留了{ detail }这一个事件对象入参位置,完全忽略了递归传值。
  • 每次递归触发时,函数都会重新读取组件初始的this.tree数据源、重复执行状态更新逻辑,既没有处理传入的子树参数,也没有终止递归的判断出口,最终形成无终止的自调用循环,撑爆调用栈。
  • 核心设计问题:把「纯递归遍历删除的无副作用逻辑」和「绑定事件、更新组件状态的副作用逻辑」混在同一个函数里,既没法正确传参给递归调用,还会在递归过程中重复触发状态更新。
修正实现方案

将功能拆分为两个独立部分,从根源解决递归传参和终止条件问题:

  1. 独立纯工具函数:不依赖组件实例状态,只接收待遍历树、待删除ID两个参数完成递归删除,设置清晰的递归终止条件
  2. 事件入口函数:仅负责从事件对象中提取待删除ID,调用纯工具函数计算新树结构,触发组件状态更新

修正后的完整代码实现:

// 纯递归删除工具:无外部依赖、无副作用
function deleteNodeRecursively(tree, targetId) {
  // 过滤当前层级和目标ID匹配的节点
  const currentLevelFiltered = tree.filter(node => node.id !== targetId)
  // 处理保留节点的子树
  return currentLevelFiltered.map(node => {
    // 递归终止条件:节点没有子节点时直接返回,不再向下遍历
    if (!node.children?.length) return node
    // 存在子节点则递归调用自身处理子树
    return {
      ...node,
      children: deleteNodeRecursively(node.children, targetId)
    }
  })
}

// 事件触发入口:仅处理事件逻辑、状态更新
function _worktreeItemDelete({ detail }) {
  const currentId = detail.item.id
  const updatedTree = deleteNodeRecursively(this.tree, currentId)
  this.set("tree", updatedTree)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.24 13:45:08