
本文介绍一种通用的递归函数实现,用于从任意深度嵌套的对象数组中移除所有 `_id` 匹配的目标项(包括顶层元素及其子级 `assets` 中的节点),并保持其余结构完整。
在处理树形或嵌套结构的数据(如带子资源的文档、菜单、权限配置等)时,常需根据唯一标识(如 _id)精准剔除某节点——该节点可能位于顶层,也可能深藏于多层 assets、children 或其他自定义子数组中。此时,简单的 filter() 或 findIndex() 无法覆盖全路径,必须采用递归遍历 + 原地过滤策略。
以下是一个健壮、可复用的递归过滤函数:
function removeIdFromArray(array, idToRemove) {
if (!Array.isArray(array)) return array;
return array.filter((element) => {
// 若当前元素自身_id匹配,直接排除(不进入子级处理)
if (element._id === idToRemove) {
return false;
}
// 若存在子数组(如 assets),递归处理并更新引用
if (Array.isArray(element.assets)) {
element.assets = removeIdFromArray(element.assets, idToRemove);
}
// 保留该元素(即使其子级被删减,只要自身未被移除即返回 true)
return true;
});
}✅ 使用示例:
const arrayToBeFiltered = [
{ _id: "1", assets: [{ _id: "2" }, { _id: "3" }] },
{ _id: "4", assets: [{ _id: "5" }] }
];
// 移除 _id === "3" → 仅删除第二项中的子对象
console.log(removeIdFromArray(arrayToBeFiltered, "3"));
// 输出:
// [
// { _id: "1", assets: [{ _id: "2" }] },
// { _id: "4", assets: [{ _id: "5" }] }
// ]
// 移除 _id === "4" → 删除整个第二项(顶层匹配)
console.log(removeIdFromArray(arrayToBeFiltered, "4"));
// 输出:
// [
// { _id: "1", assets: [{ _id: "2" }, { _id: "3" }] }
// ]⚠️ 注意事项:
- 函数原地修改子数组引用(如 element.assets = ...),但不修改原始输入数组以外的对象属性,符合不可变数据流友好原则(返回新数组,内部结构按需重建);
- 支持任意嵌套层级,只需将子数组字段名(如 "assets")在逻辑中扩展为可配置参数(进阶版可封装为 removeById(array, id, childrenKey = 'assets'));
- 若对象可能存在多个不同名称的子数组(如 children、items、nodes),建议统一数据结构,或增强函数支持多键递归;
- 严格匹配 _id 字符串值,如需模糊匹配或类型兼容(如数字 ID),请在比较前做类型归一化(例如 String(element._id) === String(idToRemove))。
该方案简洁、高效、无副作用,适用于前端状态管理、API 响应预处理及配置驱动型 UI 的动态数据裁剪场景。










