You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不可变更新嵌套数组遇引用相等问题求助

问题原因与解决方案

问题根源

你的update函数直接将原对象dest作为reduce的初始累加器acc,这意味着整个函数没有创建新的顶层对象,而是直接修改了原对象的属性,最终返回的updated其实就是原obj的引用。所以updated.a和obj.a自然指向同一个数组(即使你创建了新数组赋值给acc[key],但acc本身就是原对象,相当于直接修改了原对象的a属性,updated和obj是同一个引用)。

修复方案

要实现不可变更新,核心是从原对象的副本开始修改,而不是直接操作原对象。只需要修改reduce的初始值为原对象的浅拷贝即可:

function update(dest, source) {
  // 用原对象的浅拷贝作为累加器初始值,避免修改原对象
  return Object.entries(source).reduce((acc, [key, val]) => {
    if (Array.isArray(val)) {
      acc[key] = [...val];
    } else if (isPlainObject(val)) {
      // 递归更新嵌套对象,update已返回新对象,无需额外展开
      acc[key] = update(dest[key], source[key]);
    } else {
      acc[key] = val;
    }

    return acc;
  }, {...dest}); // 关键修改:创建原对象的副本
}

function isPlainObject(obj) {
  return Object.prototype.toString.call(obj) === '[object Object]';
}

const obj = {
  a: [1, 2],
};

const updated = update(obj, {
  a: [1, 2]
});

console.log(updated.a === obj.a); // 输出 false

额外说明

  • 修改后,updated是一个全新的顶层对象,其a属性是新创建的数组,因此updated.a !== obj.a符合预期。
  • 对于嵌套对象,递归调用update时同样会创建对应层级的副本,保证整个嵌套结构的不可变性。

内容的提问来源于stack exchange,提问作者Andy Jessop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 18:39:41