原型式继承本身不直接提供只读属性机制,但可通过 object.defineproperty 在原型上设置 writable: false 和 configurable: false 实现属性级只读;也可用 object.create 构建只读原型链,或通过 getter 模拟更灵活的只读语义。

原型式继承本身不直接提供只读属性机制,但可以通过结合 Object.defineProperty 与原型链控制,在继承关系中让子对象“看到”但无法修改父对象上的特定属性。
在原型上定义不可写、不可配置的属性
只读性需由属性描述符保证,不是继承方式决定的。可在原型对象上用 Object.defineProperty 显式设置 writable: false 和 configurable: false:
- 属性必须定义在原型(而非实例)上,确保所有继承者共享同一属性定义
-
writable: false阻止赋值操作(严格模式下会报错,非严格模式静默失败) -
configurable: false防止后续通过defineProperty改写描述符或删除该属性
使用 Object.create 构建只读原型链
用 Object.create 创建干净原型,并在其上定义只读属性,再让实例继承它:
- 先创建一个空对象作为原型
- 对该原型调用
Object.defineProperty添加只读属性(如version) - 用该原型创建新对象:
const obj = Object.create(readonlyProto) - 此时
obj.version可读,但obj.version = 2不生效
注意:只读是属性级的,不是对象级的
原型上的只读属性仅限制该属性本身;其他可写属性仍可修改,实例也可添加自有属性:
- 不能通过
obj.prop = newValue修改只读属性,但可以obj.newField = 'ok' - 若想彻底冻结整个原型对象,可用
Object.freeze(prototype),但冻结后也无法扩展新属性 - 只读属性不影响 getter/setter——如果定义了 getter,可保持只读语义,且更灵活(比如返回计算值)
替代方案:用 getter 模拟只读语义
比数据属性更安全的方式是在原型上定义 getter,不设 setter:
- 访问时执行逻辑,返回值不可被简单赋值覆盖
- 即使尝试
obj.id = 123,也不会报错也不会生效(除非显式定义了 setter) - 适合需要动态计算、依赖上下文或封装内部状态的场景











