
javascript 中对象是引用类型,`reduce` 回调中直接修改 `case_data`(即原数组中对象的引用)会导致原始 `sourcearr` 被污染;正确做法是创建新对象而非就地修改。
在你提供的代码中,问题根源在于这行逻辑:
case_data.appointment = 'DD/MM/YYYY - hh:mm:ss A' case_data.name = 'Name'
虽然 case_data 是 reduce 的当前迭代项,但它并非独立副本,而是 sourceArr 中原始对象的直接引用。因此,对 case_data 属性的赋值操作,实质上是在修改 sourceArr 中对应对象本身——这违反了函数式编程中“不可变性”(immutability)的基本原则,也与 Redux 等状态管理理念背道而驰。
✅ 正确做法:返回全新对象,不触碰原数据
应使用对象展开语法({...case_data, ...newProps})或 Object.assign() 创建浅拷贝,并覆盖指定字段:
let refined_data = newArr.reduce((acc, case_data) => {
// ✅ 安全:基于原对象创建新对象,不修改 sourceArr
return {
...case_data,
appointment: 'DD/MM/YYYY - hh:mm:ss A',
name: 'Name'
};
}, {});⚠️ 注意:{...case_data} 仅执行浅拷贝。若 case_data 内部含有嵌套对象(如 case_data.patient.address),仍需深度克隆(可借助 structuredClone() 或 Lodash 的 cloneDeep)。
? 额外优化建议
- 避免轮询 window.sourceArr:setInterval + clearInterval 方式脆弱且低效。推荐改用 MutationObserver 监听全局变量注入,或由数据提供方主动触发事件(如 window.dispatchEvent(new CustomEvent('sourceReady', { detail: data })))。
-
reduce 的初始值需匹配预期结构:你传入 {} 作为初始累加器,但 filter 后的 newArr 可能为空数组(无匹配项),此时 reduce 不执行回调,直接返回 {} —— 这是合理的;但若期望始终返回单个对象,建议补充空值校验:
const matched = sourceArr.find(data => data.case_id === current_case); const refined_data = matched ? { ...matched, appointment: '...', name: '...' } : null;
✅ 总结
| 错误行为 | 正确替代 |
|---|---|
| case_data.name = 'X'(直接赋值) | return { ...case_data, name: 'X' }(返回新对象) |
| 依赖副作用修改输入 | 所有变换均通过纯函数返回新数据 |
| 忽略嵌套对象的可变性 | 深度克隆复杂嵌套结构(必要时) |
遵循“永不直接修改输入对象”的原则,不仅能避免 sourceArr 被意外污染,更能提升代码可预测性、可测试性与协作友好度。










