为何使用push方法会覆盖对象中数组的全部内容?
宠物记录管理功能中push数据覆盖原有数组的问题解决
问题情况
在TypeScript开发宠物记录管理功能时,调用updateRecord函数向对象内的数组添加新宠物数据时,数组原有内容被意外覆盖。相关代码及逻辑如下:
enum Gender { male = "M", female = "F", } // pet attributes interface petAttributes { age: number; name: string; gender: Gender; } // pet attributes acc to color interface petDetails { [color: string]: Array<petAttributes>; } // details and attributes acc to breed interface petType { [type: string]: petDetails; } // final dog record let dogRecord: petType = { labrador: { black: [ { age: 1, name: "bhalu", gender: Gender.female, }, { age: 2, name: "lily", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, } ], yellow: [ { age: 1, name: "bhalu", gender: Gender.female, }, { age: 2, name: "lily", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, ], chocolate: [ { age: 1, name: "bhalu", gender: Gender.female, }, { age: 2, name: "lily", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, ], }, shitzu: { blackWhite: [ { age: 1, name: "bhalu", gender: Gender.female, }, { age: 2, name: "lily", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, ], }, dalmation: { blackWhite: [ { age: 1, name: "bhalu", gender: Gender.female, }, { age: 2, name: "lily", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, ], }, viszla: { brown: [ { age: 1, name: "bhalu", gender: Gender.female, }, { age: 2, name: "lily", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, ], }, boxer: { brown: [ { age: 1, name: "bhalu", gender: Gender.female, }, { age: 2, name: "lily", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, ], mix: [ { age: 1, name: "bhalu", gender: Gender.female, }, { age: 2, name: "lily", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, ], white: [ { age: 1, name: "bhalu", gender: Gender.female, }, { age: 2, name: "lily", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, { age: 2, name: "", gender: Gender.female, }, ], }, }; const updateRecord = ({ type, breed, age, name, color, gender, }: any) => { if (type === allPets.dog) { for (const property in dogRecord) { if (breed === property) { let newPet: petAttributes = { age, name, gender, }; console.log(dogRecord[property][color]); dogRecord[property][color].push(newPet); } else { dogRecord[breed] = { [color]: [ { age, name, gender, }, ], }; } } } }; // update record with new dog of existing color updateRecord({ type: allPets.dog, breed: "labrador", color: "black", age: 1, name: "rio", gender: Gender.female, });
原逻辑意图:updateRecord接收参数后,当类型为狗时,遍历dogRecord属性,匹配到目标breed就push新宠物到对应颜色数组;否则为该breed创建新的颜色数组。但实际执行时push操作会覆盖原有数组内容。
问题原因
核心错误在于遍历dogRecord的循环逻辑:
- 当遍历到与目标breed不匹配的属性时,
else分支会直接覆盖dogRecord[breed]的整个对象。 - 比如更新labrador的black数组时,遍历到shitzu、dalmation等其他breed时,都会触发else分支,把labrador的原有记录替换成仅包含新宠物的数组,导致之前push的内容被覆盖。
修复后的代码
重构updateRecord函数,去掉不必要的遍历,直接检查目标breed和颜色的存在性:
const updateRecord = ({ type, breed, age, name, color, gender, }: { type: typeof allPets.dog; breed: string; age: number; name: string; color: string; gender: Gender; }) => { if (type === allPets.dog) { // 检查breed是否存在 if (dogRecord[breed]) { const breedDetails = dogRecord[breed]; // 检查color数组是否存在 if (breedDetails[color]) { // 存在则push新宠物 breedDetails[color].push({ age, name, gender }); } else { // 不存在则创建新数组并添加 breedDetails[color] = [{ age, name, gender }]; } } else { // breed不存在则创建新条目 dogRecord[breed] = { [color]: [{ age, name, gender }], }; } } };
修复要点
- 移除了遍历
dogRecord的循环,避免多次覆盖目标breed的记录 - 先判断目标breed是否存在,再处理对应颜色的数组
- 完善了参数类型定义,替代原有的
any类型,增强类型安全性
内容的提问来源于stack exchange,提问作者user2452537
相关产品推荐
相关产品推荐

