构造函数中合并配置的核心是用户值覆盖默认值,推荐用展开运算符或object.assign({},defaults,options)实现浅合并;嵌套对象需单独处理或深合并;解构赋值适合扁平参数。

构造函数里合并默认配置和自定义参数,核心是“用用户传入的值覆盖默认值,其余保留默认”,关键在合并时机、方式和是否深拷贝。
直接在 constructor 中合并
最常见做法:把默认配置写成对象字面量或静态属性,再用 Object.assign() 或展开运算符合并。
- 推荐用空对象作为目标,避免污染原始默认配置
- 顺序很重要:默认配置在前,用户配置在后,才能实现“用户覆盖默认”
- 示例:
class Modal {
constructor(options = {}) {
const defaults = { width: 400, title: '', animation: true, closable: true };
this.config = { ...defaults, ...options }; // 或 Object.assign({}, defaults, options)
}
}
用静态 defaults 属性统一管理
适合组件库或可复用类,把默认值抽离为类的静态属性,便于维护和继承。
- selectize.js 就是这么做的:它在
Selectize.defaults中集中定义所有默认项 - 构造时合并:
Object.assign({}, Selectize.defaults, settings) - 好处是用户只需传自己关心的字段,不需重复写全量配置
嵌套对象需要深合并?谨慎判断
如果配置里有嵌套结构(比如 { api: { timeout: 5000, headers: {} } }),用 展开运算符或 Object.assign() 会整体替换,不是递归合并。
- 例如:默认
headers: { 'X-App': 'v1' },用户只传{ headers: { 'Authorization': 'xxx' } }→ 最终只剩 Authorization,X-App 丢失 - 真需要深合并,可用
lodash.merge或轻量 deepMerge 函数,但多数场景浅合并已够用 - 更稳妥的做法是:对关键嵌套字段单独处理,比如
headers: { ...defaults.headers, ...options.headers }
解构赋值 + 默认值(适合简单参数)
如果参数结构固定、层级扁平,也可以跳过对象合并,直接解构并设默认值。
- 示例:
constructor({ width = 400, title = '', animation = true, ...rest } = {}) { this.config = { width, title, animation, ...rest }; } - 优点:语义清晰、类型提示友好(尤其配合 TypeScript)
- 缺点:无法自动继承未声明的字段,灵活性略低











