JavaScript中实现只读属性需用Object.defineProperty()或defineProperties()设writable: false,配合configurable: false防修改;仅浅只读,深只读需Object.freeze()递归冻结;类中推荐用无setter的getter模拟只读。

JavaScript 中通过属性描述符实现只读属性,核心是使用 Object.defineProperty() 或 Object.defineProperties() 设置属性的 writable: false,并通常配合 configurable: false 防止被重新配置。
设置单个只读属性
用 Object.defineProperty() 为对象添加或修改属性,明确指定 writable: false:
-
writable: false表示该属性值不可被赋值操作(=)更改,尝试修改会静默失败(非严格模式)或抛出TypeError(严格模式) - 建议同时设
configurable: false,避免属性被删除或描述符被再次修改 - 注意:只读性仅针对属性本身,若属性值是对象,其内部属性仍可修改(即浅只读)
示例:
const obj = {};
Object.defineProperty(obj, 'PI', {
value: 3.14159,
writable: false,
enumerable: true,
configurable: false
});
obj.PI = 3; // 无效(非严格模式),或报错(严格模式)
delete obj.PI; // false(configurable 为 false,删除失败)
批量定义多个只读属性
使用 Object.defineProperties() 一次性设置多个属性的描述符:
立即学习“Java免费学习笔记(深入)”;
- 适合初始化时批量声明常量或配置项
- 每个属性需独立指定
value和writable: false - 可统一控制
enumerable和configurable
示例:
const Constants = {};
Object.defineProperties(Constants, {
MAX_RETRY: { value: 3, writable: false, enumerable: true, configurable: false },
TIMEOUT: { value: 5000, writable: false, enumerable: true, configurable: false },
ENV: { value: 'production', writable: false, enumerable: true, configurable: false }
});
创建真正不可变的对象(深只读)
原生属性描述符只能实现“浅只读”。如需整个对象及其嵌套属性都不可改,需递归冻结:
-
Object.freeze(obj)是最简方式:它将对象自身所有自有属性设为writable: false、configurable: false,并递归冻结可枚举的自有对象属性 - 注意:
freeze不处理原型链上的属性,也不冻结不可枚举属性或 Symbol 属性(除非显式定义) - 对已有对象调用
freeze后,无法新增、删除、重配置属性,也无法修改值(基本类型)或引用(对象类型)
示例:
const config = {
api: { baseUrl: 'https://api.example.com' },
debug: true
};
Object.freeze(config);
config.debug = false; // 失败
config.api.baseUrl = 'http://test'; // 仍成功 —— 因为 api 对象未被冻结
Object.freeze(config.api); // 需手动冻结嵌套对象
ES6 class 中模拟只读实例属性
类中无法直接用 defineProperty 声明只读字段,但可通过 getter 实现逻辑只读:
- 在构造函数内用
Object.defineProperty绑定实例属性 - 或定义无 setter 的 getter(推荐,语义清晰且支持继承)
- 注意:getter 方式不能阻止通过
Object.defineProperty覆盖该属性,如需强保护仍需结合configurable: false
示例:
class Circle {
constructor(radius) {
this._radius = radius;
Object.defineProperty(this, 'radius', {
get() { return this._radius; },
enumerable: true,
configurable: false
});
}
}
const c = new Circle(5);
c.radius = 10; // 无效(无 setter,赋值被忽略)


















