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

编写可合并任意数量对象并保留首次出现键值的函数——问题排查与修正

解决对象合并时保留首次出现键值的问题

我懂你的需求:你需要一个能合并任意数量对象的函数,而且当多个对象有相同键名时,要保留第一次出现的那个值。但你当前用Object.assign的写法刚好和预期相反,因为Object.assign()的特性是后面的对象会覆盖前面对象的同名属性——这就是为什么你的测试里foo最终变成了13,而不是你想要的5。

修正后的函数实现

我们需要换个思路:按顺序遍历所有传入的对象,只把结果对象里还没有的键加进去。这样就能保证先出现的键值不会被后续的同名键覆盖。

写法一:基础循环版

function zip(...objects) {
  const mergedObj = {};
  
  // 逐个处理每个传入的对象
  for (const obj of objects) {
    // 遍历当前对象的所有自有键
    for (const key of Object.keys(obj)) {
      // 只有当键还没在结果对象里时,才添加
      if (!(key in mergedObj)) {
        mergedObj[key] = obj[key];
      }
    }
  }
  
  return mergedObj;
}

写法二:用reduce简化版

如果你喜欢更简洁的函数式写法,也可以用Array.reduce来实现:

function zip(...objects) {
  return objects.reduce((merged, currentObj) => {
    Object.keys(currentObj).forEach(key => {
      if (!(key in merged)) {
        merged[key] = currentObj[key];
      }
    });
    return merged;
  }, {});
}

测试验证

用你的示例测试一下:

const objects = [ { foo: 5, bar: 6 }, { foo: 13, baz: -1 } ];
console.log(zip(...objects)); // 输出:{ foo: 5, bar: 6, baz: -1 }

完全符合你的预期!

为什么原写法不行?

再强调一下:Object.assign({}, ...objects)会把objects数组里的对象按顺序传入assign,也就是先合并第一个对象,再用第二个对象的属性去覆盖第一个的同名属性——这和你要的"保留首次值"逻辑刚好相反,所以才会得到错误的结果。

内容的提问来源于stack exchange,提问作者Mr.Mox

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 13:32:33