合并复杂配置对象时继承丢失,是因为Object.assign和展开运算符只复制自身可枚举属性,不处理原型链,导致原型方法和默认配置缺失;正确做法是先创建实例再合并,或手动提取原型属性显式合并。
合并复杂配置对象时,继承丢失不是因为“继承被删了”,而是因为合并操作绕过了原型链——Object.assign、展开运算符({...a, ...b})等默认只处理对象自身的可枚举属性,原型上的方法或默认配置根本不会被复制过去。结果是:新对象看似结构完整,实则缺失关键行为或默认值。
原型上的配置(比如 BaseConfig.prototype.defaults 或 Service.prototype.timeout)是共享的、动态可维护的。一旦用浅合并覆盖整个对象,这些原型级能力就断连了。
Object.assign({}, baseConfig, userConfig) → 新对象没有 baseConfig 的原型,defaults 方法调不了Object.assign(this, userConfig) 合并到实例自身,保留原型链完整如果确实要将原型上的默认配置“拍平”进最终对象(例如生成纯 JSON 配置),必须手动读取,不能指望合并工具自动抓取:
const defaults = Object.getPrototypeOf(baseConfig)?.defaults
mergeDeep({ ...defaults }, userConfig),而不是 Object.assign
Object.create(null)),Object.getPrototypeOf 返回 null,需提前判断有人为避免原型污染用 Object.create(null) 创建配置对象,但这会让对象彻底脱离原型链——没有 toString、hasOwnProperty,也无法继承任何基类方法,后续所有合并、校验、序列化都可能出错。
Object.create(null)
Map 存储键值,避免污染风险Object.getPrototypeOf(config) === null → 就是人为切断了,得重构初始化逻辑某些旧版编译器会把类转换成带 Object.create(null) 或直接操作 __proto__ 的代码,导致实例原型链异常。这类问题在合并配置前就已存在,但直到调用原型方法时才暴露。
Object.getPrototypeOf(inst),确认它指向预期的原型对象Object.setPrototypeOf(inst, Constructor.prototype)
inst instanceof ExpectedClass,失败即告警