如何在嵌套数组中指定对象前插入新元素

本文介绍一种递归遍历嵌套对象数组的方法,精准定位目标对象(按 `name` 字段匹配),并在其所在 `children` 数组中**在其前方插入新对象**,适用于任意深度的树形结构。

在处理树状结构数据(如菜单、分类、组织架构)时,常需动态向某节点的子列表中插入新项。关键难点在于:目标对象可能位于任意嵌套层级,且插入位置必须严格为「该目标对象之前」,而非父级 children 数组末尾或任意位置。

以下是一个健壮、可复用的解决方案:

function addObjectBefore(arr, targetName, newObj) {
  if (!Array.isArray(arr)) return;

  for (let i = 0; i < arr.length; i++) {
    const item = arr[i];

    // ✅ 优先检查当前层级的 children 是否包含目标对象
    if (Array.isArray(item.children)) {
      const targetIndex = item.children.findIndex(obj => obj.name === targetName);
      if (targetIndex !== -1) {
        item.children.splice(targetIndex, 0, newObj); // 在目标前插入
        return; // ✅ 找到即终止,避免重复插入
      }
    }

    // ❌ 未在当前 children 中找到 → 递归搜索更深层的 children
    if (Array.isArray(item.children)) {
      addObjectBefore(item.children, targetName, newObj);
    }
  }
}

使用示例

const data = [
  {
    name: 'Fruit',
    children: [{ name: 'Apple' }, { name: 'Banana' }, { name: 'Fruit loops' }],
  },
  {
    name: 'Vegetables',
    children: [
      {
        name: 'Green',
        children: [{ name: 'Broccoli' }, { name: 'Brussels sprouts' }],
      },
      {
        name: 'Orange',
        children: [{ name: 'Pumpkins' }, { name: 'Carrots' }],
      },
    ],
  },
];

addObjectBefore(data, 'Pumpkins', { name: 'new name' });

console.log(JSON.stringify(data, null, 2));
// 输出中,'Orange'.children 将变为:
// [{ name: 'Pumpkins' } → 前插入 → { name: 'new name' }, { name: 'Pumpkins' }, { name: 'Carrots' }]

⚠️ 注意事项

  • 匹配逻辑严格依赖 name 字段:确保目标对象的 name 值唯一或你接受首个匹配项;
  • 仅影响 children 数组:本函数只在 item.children 中查找和插入,不修改顶层同名对象本身;
  • 单次插入:return 语句保证首次命中即停止,避免多层重复插入;
  • 空值防护:已添加 Array.isArray() 检查,防止传入非数组或 undefined.children 报错;
  • 不可变需求? 若需保持原数组不变,请先深拷贝(如 structuredClone(data))再操作。

该方法简洁、高效、无副作用,是处理前端树形数据动态编辑的实用工具函数。