实现层级配置的核心是利用原型链就近查找机制,通过object.create构建继承链,封装config工厂确保不可变性,并用defineproperty控制属性行为。

要实现一个支持层级扩展的对象配置,核心是利用 JavaScript 原型链的“就近查找”机制——属性先查自身,没有就沿 __proto__ 向上找。这样就能让低层配置继承高层默认值,同时允许局部覆盖,不破坏原始配置。
用 Object.create 构建层级原型链
这是最清晰、语义明确的方式:每一层配置对象都以它的上层为原型。
- 顶层配置(如默认值)作为基础原型,只定义通用字段,不实例化
- 中间层(如环境配置)用
Object.create(defaults)创建,可覆盖或新增属性 - 具体实例(如某服务配置)再基于中间层创建,只写差异项
例如:
const defaults = { timeout: 5000, retries: 3, baseUrl: 'https://api.example.com' };
const staging = Object.create(defaults);
staging.timeout = 8000;
staging.baseUrl = 'https://staging.api.example.com';
const userSvc = Object.create(staging);
userSvc.retries = 1;
userSvc.path = '/users';
console.log(userSvc.timeout); // 8000(来自 staging)
console.log(userSvc.baseUrl); // 'https://staging.api.example.com'
console.log(userSvc.path); // '/users'(自身独有)
避免直接修改内置原型,封装安全的配置工厂
直接改 Object.prototype 或 Array.prototype 会污染全局环境,应封装成可复用的构造函数或工厂函数。
- 定义一个
Config构造函数,接收父配置作为参数 - 内部用
Object.create(parent || {})设置原型 - 提供
extend()方法返回新配置,保持不可变性
这样每次扩展都生成新对象,不会意外影响上游配置。
配合 defineProperty 控制属性行为
某些配置项需要只读、不可枚举或不可删除(比如 env 或 version),可用 Object.defineProperty 精确控制。
- 在顶层配置中定义
env为enumerable: false, writable: false - 子配置即使尝试赋值也不会生效,保证一致性
- 避免用简单赋值覆盖关键字段,提升配置可靠性
注意原型链断裂与 constructor 修复
用 Object.create 创建的对象,其 constructor 指向 Object,不是原始构造函数。如果需识别配置类型,可手动设置:
-
child.constructor = Config(若用了构造函数) - 或更稳妥地:添加
isConfig: true这类标识属性 - 避免依赖
instanceof判断,因原型链可能被替换











