跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

如何通过 展开运算符 优雅实现对原始配置对象中“默认参数”的深度覆盖

展开运算符仅支持浅层合并,无法深度覆盖嵌套对象;需结合递归deepMerge函数实现优雅深度合并,支持数组策略与解构默认值。 用展开运算符(
...
)做深度覆盖默认配置,单靠它本身做不到——它只做浅层合并。要“优雅”实现深度覆盖,得把展开运算符作为基础工具,再配合递归合并逻辑。 为什么展开运算符不能直接深度覆盖 展开运算符对对象是浅拷贝:遇到嵌套对象时,它不会递归遍历子属性,而是直接替换整个子对象。 例如:
const defaults = { api: { url: '/api', timeout: 5000 }, debug: false }; const config = { api: { url: '/v2/api' } }; const merged = { ...defaults, ...config }; // 结果:{ api: { url: '/v2/api' }, debug: false } // ❌ timeout 被丢掉了 —— 因为整个 defaults.api 被 config.api 替换了
优雅方案:用展开运算符 + 递归合并函数 保留展开语法的简洁性,把深度逻辑封装进一个纯函数,调用时仍保持声明式风格。 示例实现(TypeScript/JS 都适用):
function deepMerge(target, source) { if (typeof target !== 'object' || target === null || typeof source !== 'object' || source === null) { return source; } const output = { ...target }; // 浅拷贝目标,避免污染 for (const key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { output[key] = deepMerge(output[key], source[key]); } } return output; } // 使用方式(依然用展开运算符组织参数) const finalConfig = deepMerge(defaults, userConfig);
✅ 优势:调用干净、可复用、支持任意嵌套层级、不依赖外部库。 进阶技巧:支持数组合并策略(如 concat 或覆盖) 默认 deepMerge 把数组当普通对象处理(逐项递归),但有时你希望
features: ['a']
和
features: ['b']
合并成
['a','b']
。 只需在
deepMerge
中加一层判断: 检测到双方都是数组 → 按需
concat
或用
[...target, ...source]
或提供选项:
deepMerge(defaults, config, { array: 'concat' })
这样既保持展开运算符的表达力,又让深度逻辑可配置。 实用建议:结合解构 + 默认值提升可读性 在函数接收配置时,可先深合并在解构,让默认值语义更清晰:
function createService(options = {}) { const config = deepMerge( { api: { url: '/api', timeout: 5000 }, debug: false }, options ); const { api: { url, timeout }, debug } = config; // 解构即带默认 // ... }
比层层
options.api?.url ?? defaults.api.url
更简洁、更易维护。

相关文章