原型链本身不直接提供“只读保护”,但可通过 object.defineproperty(writable: false + configurable: false)或仅定义 getter 在原型上实现所有实例共享的只读属性,需防实例赋值屏蔽及引用类型内部修改风险。

原型链本身不直接提供“只读保护”,但它能配合 Object.defineProperty 或 get 访问器,在原型上定义不可写属性,从而让所有继承该原型的实例都表现出只读行为。
在原型对象上定义只读属性
把只读逻辑放在 Constructor.prototype 上,所有实例都会共享这个受控访问方式:
- 用
Object.defineProperty设置writable: false和configurable: false,确保属性值不能被覆盖、也不能被重新配置 - 或直接用
get定义 getter,不提供set—— 这样赋值操作会被静默忽略(非严格模式)或报错(严格模式)
例如:
function User(name) { this.name = name; }<br>User.prototype.getRole = function() { return 'user'; };<br>// 在原型上添加只读属性<br>Object.defineProperty(User.prototype, 'role', {<br> get() { return 'user'; },<br> enumerable: true,<br> configurable: false<br>});<br><br>const u = new User('Alice');<br>console.log(u.role); // 'user'<br>u.role = 'admin'; // 无效<br>console.log(u.role); // 仍为 'user'
利用属性屏蔽规则防止意外覆盖
当实例自身没有该属性时,读取会沿原型链向上查找;但如果在实例上强行赋值同名属性(如 u.role = 'admin'),JavaScript 会**在实例自身创建一个新属性**,从而屏蔽原型上的 role —— 这反而破坏了只读意图。
要避免这点,可:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 在原型上把
configurable: false,阻止后续通过defineProperty修改描述符 - 结合
writable: false+configurable: false,使属性彻底锁定(连删除都不允许) - 不依赖实例赋值,改用方法或
Symbol键控制访问入口
注意原型上引用类型属性的共享风险
如果只读属性是一个对象或数组(比如 User.prototype.permissions = ['read']),虽然属性名本身不可重赋值,但其内部值仍可被修改 —— 因为 writable: false 只锁住“指向”,不冻结内容。
真正安全的做法是:
- 用
Object.freeze()冻结该对象本身(仅第一层) - 或用 getter 返回深拷贝/不可变副本(如
get permissions() { return Object.freeze(['read']); }) - 在现代环境可用
structuredClone或immer辅助
和 class 语法结合更清晰
ES6 class 本质仍是基于原型,但语法更直观:
class Product {<br> constructor(id) { this._id = id; }<br> get id() { return this._id; } // 只读访问器<br>}<br><br>Object.defineProperty(Product.prototype, 'category', {<br> value: 'general',<br> writable: false,<br> configurable: false,<br> enumerable: true<br>});
这样所有 Product 实例都拥有只读的 id(靠 getter)和只读的 category(靠原型 descriptor),且不会被实例属性意外屏蔽。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










