如何编写函数实现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
相关产品推荐
相关产品推荐

