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

如何编写函数实现JavaScript多层对象的自动Deep Spread(深层扩展)?

问题:实现JavaScript对象的深层扩展(Deep Spread)函数

我正在使用一个存储自定义库默认值的JavaScript对象,结构如下:

const defaults = {
    alpha: alpha_val,
    beta: {
      a: {
        i: beta_a_i_val,
        ii: beta_a_ii_val,
      },
      c: beta_c_val,
    },
    gamma: gamma_val,
};

目前我通过手动嵌套扩展语法覆盖默认值,写法如下:

const override = {
    ...defaults,
    beta: {
      ...defaults.beta,
      a: {
        ...defaults.beta.a,
        i: beta_a_i_newval,
      },
    },
    gamma: gamma_newval,
};

但实际的defaults对象规模较大,多次覆盖操作繁琐且代码冗余。我想知道是否可以编写函数自动完成这类“Deep Spread(深层扩展)”操作?例如只需定义新值对象:

const newvals = {
    beta: {
      a: {
        i: beta_a_i_newval,
      },
    },
    gamma: gamma_newval,
};

const overrides = someFunction(defaults, newvals)

我刚接触JavaScript,希望能得到相关实现建议。


实现方案

1. 自定义递归深层合并函数

你可以自己写一个递归函数来处理深层对象的合并,核心逻辑是:遍历新值对象的每个属性,判断属性值的类型——如果是对象(且不是null、数组),就递归合并原对象对应的属性;如果是原始值或数组,直接用新值覆盖原对象的对应属性。

示例实现:

function deepMerge(defaults, newVals) {
  // 创建新对象,避免修改原defaults
  const result = { ...defaults };
  
  // 遍历新值对象的所有自有属性
  for (const key in newVals) {
    if (newVals.hasOwnProperty(key)) {
      const defaultVal = result[key];
      const newVal = newVals[key];
      
      // 判断当前属性是否均为非数组、非null的对象
      const isBothPlainObjects = typeof defaultVal === 'object' && defaultVal !== null 
                               && typeof newVal === 'object' && newVal !== null
                               && !Array.isArray(defaultVal) && !Array.isArray(newVal);
      
      if (isBothPlainObjects) {
        // 递归合并嵌套对象
        result[key] = deepMerge(defaultVal, newVal);
      } else {
        // 原始值或数组,直接覆盖
        result[key] = newVal;
      }
    }
  }
  
  return result;
}

使用方式和你预期的一致:

const overrides = deepMerge(defaults, newvals);

2. 注意事项

  • 数组处理:上述实现会直接用新数组覆盖原数组,如果需要合并数组(比如追加元素),可以单独添加数组类型的判断逻辑。
  • 循环引用:如果你的对象存在循环引用(比如obj.a = obj),递归函数会陷入死循环,新手阶段若无这类场景可暂时忽略,后续可添加循环引用检测逻辑。
  • 不可变原则:函数返回新对象,不会修改原defaults和newVals,避免意外污染原始数据。

3. 简化版实现(利用Object.assign)

如果不需要处理复杂边界情况,也可以用更简洁的递归写法:

function deepMergeSimple(defaults, newVals) {
  const merged = Object.assign({}, defaults);
  for (const key in newVals) {
    if (typeof newVals[key] === 'object' && newVals[key] !== null && !Array.isArray(newVals[key])) {
      merged[key] = deepMergeSimple(merged[key], newVals[key]);
    } else {
      merged[key] = newVals[key];
    }
  }
  return merged;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 06:50:30