Object.assign不支持原型属性继承,需结合Object.create(DEFAULT_OPTS)创建继承默认配置的对象,再用Object.assign覆盖自有属性,实现默认值委托与动态更新。

Object.assign 本身不支持原型属性的自动继承,但可以通过组合 Object.create 与 Object.assign,构建一个能“感知默认原型属性”的参数初始化引擎——关键在于:先基于默认配置对象创建新实例(保留其原型链),再用用户传入的配置覆盖自有属性。
一、为什么 Object.assign 无法直接处理原型属性
Object.assign(target, source) 只会拷贝 source 对象自身的可枚举属性,不会读取或设置原型上的属性。即使 source 的原型上有 timeout: 5000,Object.assign({}, source) 也不会把它复制过去。
所以,若想让“默认值”天然存在于原型上(便于集中维护、节省内存、支持动态更新),就不能只靠 assign,而要借助原型委托机制。
二、构建带默认原型的参数初始化引擎
核心思路:用 Object.create(defaults) 创建一个继承自默认配置的对象,再用 Object.assign 向它写入用户传入的显式配置。这样,未指定的字段会自然回退到原型上的默认值。
示例实现:
const DEFAULT_OPTS = {
timeout: 10000,
retries: 3,
method: 'GET',
headers: { 'Content-Type': 'application/json' }
};
function createOptions(userOpts = {}) {
// 创建继承自 DEFAULT_OPTS 的空对象
const opts = Object.create(DEFAULT_OPTS);
// 仅覆盖自有属性(不污染原型)
Object.assign(opts, userOpts);
return opts;
}
使用效果:
-
createOptions({ timeout: 3000 })→timeout是 3000(自有),retries是 3(来自原型) -
createOptions({})→ 所有字段均来自原型,默认值生效 -
createOptions().hasOwnProperty('timeout')→false(说明是原型属性,非自有)
三、增强实用性:支持深默认与不可变保护
实际业务中,常需处理嵌套默认值(如 headers)和防止用户意外修改默认对象。可稍作升级:
- 对引用类型默认值(如
headers),在Object.create后,用Object.assign浅合并,避免共享引用;必要时用结构克隆(如{...DEFAULT_OPTS.headers, ...userOpts.headers}) - 用
Object.freeze(DEFAULT_OPTS)冻结默认对象,防止被误改 - 添加类型校验或字段白名单,提升健壮性(例如过滤掉非法 key)
四、注意事项与边界场景
这种模式不是万能的,需注意:
-
for...in会遍历原型属性,如需只处理自有属性,请用Object.keys()或Object.getOwnPropertyNames() - JSON 序列化(
JSON.stringify)忽略原型属性,若需导出完整配置,应先Object.assign({}, opts)落实所有字段 - 函数类型的默认方法(如
onError: () => {})可安全放在原型上,调用时this指向当前 opts 实例,符合直觉

















