检测属性是否可修改需通过object.getownpropertydescriptor获取描述符并检查writable字段:数据属性看writable值,访问器属性看set是否存在;该方法仅检查自有属性,不查原型链。

JavaScript 中检测属性是否可被修改,关键在于检查该属性的 writable 特性(descriptor),它属于属性描述符(property descriptor)的一部分。直接读取属性值无法判断其是否可写,必须通过 Object.getOwnPropertyDescriptor() 或 Reflect.getOwnPropertyDescriptor() 获取描述符来确认。
使用 getOwnPropertyDescriptor 检查 writable
这是最标准、可靠的方式:获取对象自有属性的描述符,查看 writable 字段是否为 true。
- 如果返回描述符中
writable: true,表示该属性值可被赋值修改; - 若为
false(或未定义,因访问器属性没有writable),则不能通过简单赋值改变其值; - 注意:该方法只检查**自有属性**,不查找原型链上的属性。
const obj = {};
Object.defineProperty(obj, 'name', { value: 'Alice', writable: false });
console.log(Object.getOwnPropertyDescriptor(obj, 'name')?.writable); // false
obj.name = 'Bob'; // 静默失败(非严格模式)或报错(严格模式)
区分数据属性与访问器属性
属性分为两类,判断逻辑略有不同:
-
数据属性(有
value和writable):直接看writable; -
访问器属性(有
get/set):没有writable字段,是否“可修改”取决于是否存在set函数; - 可通过
descriptor.set !== undefined判断是否允许赋值(即是否有 setter)。
writable: false,若存在 set,仍可通过赋值触发 setter —— 此时“可修改”含义不同,需按实际需求判断。
注意不可扩展、密封、冻结对象的影响
对象状态会影响属性是否能被重新定义,但不等同于单个属性的可写性:
-
Object.preventExtensions():禁止新增属性,不影响已有属性的 writable; -
Object.seal():密封后属性不可配置(configurable: false),但若原本writable: true,仍可修改值; -
Object.freeze():冻结后所有数据属性变为writable: false且configurable: false,是最强限制。
因此,仅靠 isFrozen() 等方法不能替代对具体属性描述符的检查。
兼容性与实用小技巧
现代环境基本都支持 getOwnPropertyDescriptor,但需注意:
- ES5+ 环境才保证该 API 可靠;
- 对于 Proxy 对象,描述符可能被拦截,结果取决于 handler 实现;
- 简写判断函数可封装为:
function isWritable(obj, key) {<br> const desc = Object.getOwnPropertyDescriptor(obj, key);<br> return !!desc && ('writable' in desc ? desc.writable : !!desc.set);<br>}
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











