javascript中通过属性描述符实现读写分离:用writable: false设只读属性,或用get/set定义访问器属性;需协同configurable和enumerable确保行为符合预期。

JavaScript 中通过属性描述符(Property Descriptor)可以精确控制对象属性的行为,实现读写分离——即让属性可读但不可写,或可写但不可读(后者较少见,通常配合 getter/setter 实现逻辑隔离)。核心在于使用 Object.defineProperty 或 Object.defineProperties 设置 writable、get、set 等描述符字段。
用 writable: false 实现只读属性
这是最直接的读写分离方式:禁止修改,但允许读取。适用于常量、配置项或防止意外覆盖的内部状态。
- 设置
writable: false后,对属性赋值会被静默忽略(非严格模式)或抛出TypeError(严格模式) - 该属性仍可被
delete删除(除非同时设configurable: false) - 必须确保属性已存在,或在定义时一并声明
value
示例:
const obj = {};Object.defineProperty(obj, 'PI', {
value: 3.14159,
writable: false,
enumerable: true,
configurable: false
});
console.log(obj.PI); // 3.14159
obj.PI = 3; // 无效(非严格模式)或报错(严格模式)
用 getter/setter 实现带逻辑的读写分离
当需要对读取或写入行为添加校验、转换、副作用(如触发更新)时,应使用 get 和 set 描述符。二者可单独定义,从而真正实现“可读不可写”或“可写不可直接读”(后者需谨慎设计)。
- 只定义
get不定义set→ 属性只读(尝试写会静默失败或报错,取决于环境) - 只定义
set不定义get→ 属性不可读(读取返回undefined),但可写(适合触发副作用,如日志、缓存更新) -
get和set都定义 → 完全可控的读写逻辑,例如格式转换、权限检查
示例(只读计算属性):
_name: 'Alice',
age: 30
};
Object.defineProperty(user, 'fullName', {
get() { return this._name + ' (age: ' + this.age + ')'; },
enumerable: true,
configurable: true
});
console.log(user.fullName); // "Alice (age: 30)"
user.fullName = 'Bob'; // 无效果(非严格模式)
注意 configurable 和 enumerable 的协同影响
读写分离的效果常受其他描述符制约,不能孤立看待 writable 或 get/set。
-
configurable: false锁定属性描述符本身:无法删除、无法修改writable、enumerable、configurable,也无法把data属性转为accessor(反之亦然) -
enumerable: false使属性不参与for...in和Object.keys(),但不影响直接访问,常用于隐藏内部字段 - 一旦
configurable设为false,就再也不能恢复成可配置状态,务必谨慎
ES6 class 中的等效写法
类中无法直接用 Object.defineProperty 定义实例属性描述符,但可在构造函数或静态块中手动定义;更常见的是在类体内用 getter/setter 语法,本质仍是定义 accessor 属性。
- 类字段语法(
prop = value)定义的是可写、可枚举、可配置的数据属性 - 用
get prop() {}和set prop(val) {}定义的是 accessor 属性,默认configurable: true、enumerable: false - 若需完全控制(如设
enumerable: true),仍需在构造函数中调用Object.defineProperty
示例:
class Counter {constructor() {
this._count = 0;
Object.defineProperty(this, 'count', {
get() { return this._count; },
set(val) { if (val >= 0) this._count = val; },
enumerable: true
});
}
}
不复杂但容易忽略细节:读写分离不是单纯“不让改”,而是根据场景选择 writable 控制赋值、用 get/set 注入逻辑、靠 configurable 锁定元信息。三者组合才能稳健落地。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











