JavaScript class 无原生 readonly,但可用私有字段+get访问器(推荐)、Object.defineProperty 冻结属性、或运行时 set 检查模拟只读;核心是阻止外部修改而允许内部初始化。

JavaScript 的 class 语法本身不提供原生的 readonly 关键字(如 TypeScript 中那样),但可以通过几种实用方式模拟属性的只读行为,核心思路是:**阻止外部修改,同时允许内部初始化或使用**。
用 get 访问器 + 私有字段(推荐)
这是最现代、语义最清晰的方式,结合 # 私有字段和只读的 get 访问器:
class Person {
#name;
constructor(name) {
this.#name = name; // ✅ 内部可赋值
}
get name() {
return this.#name; // ✅ 只读暴露
}
}
const p = new Person("Alice");
console.log(p.name); // "Alice"
p.name = "Bob"; // ❌ 无效(不会报错,但无效果)
- 私有字段
#name确保外部无法直接访问或修改 -
get name()提供只读访问接口,没有对应的set,所以赋值被忽略 - 兼容性良好(现代浏览器和 Node.js 12+ 支持)
用 Object.defineProperty 冻结实例属性
在构造函数中定义不可写、不可配置的属性:
class Person {
constructor(name) {
Object.defineProperty(this, 'name', {
value: name,
writable: false, // ❌ 不可重新赋值
configurable: false, // ❌ 不可删除或重定义
enumerable: true // ✅ 可遍历
});
}
}
const p = new Person("Alice");
console.log(p.name); // "Alice"
p.name = "Bob"; // ❌ 静默失败(严格模式下会报错)
- 适合需要在实例上挂载真正不可变属性的场景
- 注意:
writable: false仅阻止赋值,不阻止对象内部属性被修改(如obj.prop.x = 1仍有效) - 若需完全冻结,可用
Object.freeze(value)配合使用
运行时检查 + 命名约定(轻量辅助)
适用于简单场景或需兼容老旧环境,靠约定和警告提醒:
立即学习“Java免费学习笔记(深入)”;
class Person {
#_name;
constructor(name) {
this.#_name = name;
}
get name() {
return this.#_name;
}
set name(value) {
console.warn("⚠️ 'name' is readonly — assignment ignored");
// 或 throw new Error("Cannot assign to readonly property 'name'");
}
}
- 显式定义
set并忽略/报错,增强开发体验 - 配合命名约定(如
_name表示“应视为只读”)提升可读性 - 不提供强保护,但能及时反馈误操作
不复杂但容易忽略:真正的只读保障依赖私有状态 + 只读接口组合,而非单靠语法糖。优先用私有字段 + getter,兼顾安全与可维护性。


















