Object.seal仅冻结对象自身属性(不可增删、不可重配置),但允许修改值;构建安全配置对象需分离数据与行为:配置放sealed实例,方法定义在freeze后的原型上,并用defineProperty按需锁定特定字段。

Object.seal 本身不作用于原型链,它只冻结对象自身的属性(不可增删、不可重配置),但允许修改已有属性的值;要构建“安全的配置对象”,关键在于把配置数据和行为逻辑分离——把可变配置放在 sealed 实例上,把方法和默认行为定义在原型上,并阻止原型被意外篡改。
用 Object.seal 封装实例配置
配置对象的核心数据应是实例自身属性。调用 Object.seal 后,这些属性无法被删除、无法被重新定义(比如改成 accessor),也无法添加新属性,但值仍可修改(例如 config.timeout = 5000 是允许的)。
- 避免直接 new Config() 后暴露裸对象,而是通过工厂函数返回 sealed 实例
- 确保所有配置项都在构造时一次性设置完成,之后不再动态添加
- 不要在 sealed 对象上挂方法——方法应统一由原型提供
把方法定义在不可修改的原型上
原型链本身不受 Object.seal 影响,所以必须额外保护:用 Object.freeze(Object.getPrototypeOf(instance)) 锁定原型对象,防止方法被覆盖或删除;同时确保原型没有可写的自有属性(否则可能被误当配置项)。
- 推荐使用 class 声明,然后 freeze 其 prototype(如 Object.freeze(Config.prototype))
- 避免在原型上定义可变状态(如 this.cache = {}),这类状态应放在实例内部或用 WeakMap 管理
- 如果需支持继承,父类原型也需提前 freeze,否则子类可能绕过限制
组合 seal + freeze + defineProperty 控制访问粒度
seal 允许改值,但某些配置项(如 env 或 apiBase)应只读。这时可在 seal 前用 Object.defineProperty 设置 { writable: false, configurable: false },再 seal 整体对象——这样既保留部分字段只读,又防止新增/删除属性。
立即学习“Java免费学习笔记(深入)”;
- 例如:Object.defineProperty(config, 'env', { value: 'prod', writable: false })
- seal 之后再尝试 config.env = 'dev' 会静默失败(非严格模式)或抛 TypeError(严格模式)
- defineProperty 配合 seal 比 Object.freeze 更灵活:freeze 会锁死所有值,而 seal + 定制 descriptor 可按需锁定特定字段
验证与防御性检查
运行时可加一层校验:在构造函数中检查 Object.isSealed(this) 是否为 true,再确认原型是否已被 freeze;还可拦截 set 操作(配合 Proxy)对非法写入给出明确提示,但注意 Proxy 会破坏 sealed 对象的原始语义,仅用于开发阶段辅助。
- 生产环境建议用 Object.isSealed 和 Object.isFrozen 配合断言做轻量检查
- 避免在 sealed 对象上使用 for...in 或 Object.keys 动态推导结构——其自有属性集已固定,应明确声明接口
- 若需序列化,JSON.stringify 会忽略不可枚举属性,确保关键配置项设为 enumerable: true


















