JS使用map方法构建层级数据时新对象未插入问题排查
问题原因分析
你定位的问题点是对的,原代码有4个核心逻辑错误:
- 给
map回调的局部参数element直接赋值不会修改原数组。JS中遍历数组拿到的element是存储了对象引用的局部变量,你直接把这个变量重新指向一个新对象,只会修改当前回调作用域内的变量指向,完全不会影响原数组里存储的内容,自然无法把新的part对象插入到结构里。 - 缺失层级存在性判断。原代码在检测到学科已经存在后,没有判断对应part(比如2ND)是否已经创建,第一次处理2ND相关字段时,学科下的children只有1ST的对象,代码根本没有走新建2ND part对象的分支,2ND的内容自然插不进去。
- 数组操作逻辑错误。原代码用
element.children["2"] = {xxx}的方式给数组加元素,不仅会把内容错塞到不匹配的part下,还会生成不符合预期的稀疏数组。 map方法误用。map是用来做数组映射、返回新数组的方法,你全程没有使用map的返回值,纯遍历场景应该用forEach,滥用map只会造成无意义的性能浪费。
修复后的实现代码
修复思路是按层级从上到下做存在性判断,每一层不存在就新建,存在就直接往对应层级的children里追加内容,不需要无意义的嵌套遍历:
const results = [ { Field: "english_1st_CQ" }, { Field: "english_1st_MCQ" }, { Field: "english_2nd_CQ" }, { Field: "english_2nd_MCQ" }, ]; const structureData = (results) => { const targetArr = []; results.forEach((item) => { if (!item.Field.includes("_")) return; // 拆分字段得到三层结构的key const [subjectName, partName, questionType] = item.Field.split("_"); // 第一层:查找/创建学科节点 let subjectNode = targetArr.find(node => node.title === subjectName); if (!subjectNode) { subjectNode = { title: subjectName, children: [] }; targetArr.push(subjectNode); } // 第二层:查找/创建part节点(1ST/2ND) let partNode = subjectNode.children.find(node => node.title === partName); if (!partNode) { partNode = { title: partName, children: [] }; subjectNode.children.push(partNode); } // 第三层:追加题型配置 partNode.children.push({ title: questionType, dataIndex: questionType }); }); return targetArr; }; console.log(structureData(results));
运行后输出的结构完全匹配需求,不会出现2ND部分丢失的问题。如果需要首字母大写格式(比如english转English、1st转1ST),可以在赋值title的时候加对应的大小写转换逻辑即可。
内容的提问来源于stack exchange,提问作者Anik Ahmed fathe
相关产品推荐
相关产品推荐

