es6类中防止外部修改只读属性的关键是私有字段(#)+只读getter封装,配合返回副本和运行时守卫。需声明#name、仅提供get name()、避免\_name约定、禁用构造函数中调用可重写方法、getter返回结构副本、关键方法添加校验逻辑。

在 ES6 类中,防止外部直接修改实例的只读核心属性,关键不是靠“阻止赋值”这一层防御,而是从设计源头切断非法访问路径——让外部根本拿不到可写的入口,也写不进真实数据。
用私有字段(#)+ getter 封装真实值
这是现代 JavaScript 中最可靠、语义最清晰的方式。私有字段天然不可被外部访问或枚举,配合只读 getter,既保持调用简洁(p.name),又杜绝绕过可能。
- 在类体顶部声明私有字段:#name = 'Alice'
- 只提供 getter,不写 setter:get name() { return this.#name }
- 外部执行 p.name = 'Bob' 会静默失败(无 setter),且 p.#name 语法报错
- 避免用 _name 这类命名约定,它只是提示,不具强制力
禁止在构造函数中调用可被重写的方法
父类初始化阶段若调用子类可能覆盖的方法,会导致 this 尚未就绪就执行逻辑,给篡改留出空隙。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 错误写法:this.init()(init 可被子类重写)
- 正确做法:把初始化逻辑收进私有方法,如 #setup(),并在 constructor 中直接调用
- 确保所有敏感状态都在 #setup 中完成,不依赖子类参与
对外暴露只读视图,而非原始引用
即使属性本身是只读的,如果返回的是对象或数组引用,外部仍可修改其内部内容。
- getter 中返回副本:get config() { return { ...this.#config } }
- 对数组用 slice() 或结构赋值:get items() { return [...this.#items] }
- 避免直接返回 this.#data,尤其当它是响应式对象或普通对象时
运行时加守卫,拒绝非受控调用
对允许子类扩展但必须保留核心流程的方法(如 save、validate),可在父类中内置检查机制。
- 在方法开头判断:if (!this.#validated) throw new Error('must call super.validate() first')
- 结合 new.target 区分直接实例化与继承:if (new.target !== Parent) { /* 子类逻辑 */ }
- 子类重写时必须显式调用 super.xxx(),否则核心校验跳过
不复杂但容易忽略:只读不是靠“锁住赋值”,而是靠“藏好钥匙”+“封死门”。私有字段是第一道墙,getter 是唯一窗口,副本返回是最后一道保险。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










