writable属性描述符控制对象属性是否可被重新赋值,需通过object.defineproperty()设置;设为false后,严格模式下赋值抛typeerror,非严格模式下静默失败,且不可逆除非configurable为true。

writable 属性描述符控制一个属性是否可以被重新赋值。它本身不主动“抛异常”,但当尝试修改一个 不可写(writable: false) 的属性时,JavaScript 引擎的行为取决于当前运行模式——严格模式下会抛出 TypeError,非严格模式下则静默失败(赋值无效,无报错)。
严格模式下:直接抛 TypeError
只要对象属性的 writable 为 false,在严格模式中对它赋值就会立即中断执行并抛出错误:
- 例如:
Object.defineProperty(obj, 'x', { value: 1, writable: false })后,执行obj.x = 2会触发TypeError: Cannot assign to read only property 'x' - 该错误无法通过
try/catch捕获到“赋值操作本身”的中间状态,但整个表达式执行会终止 - 箭头函数、普通函数内部若启用严格模式(如脚本首行
"use strict"),同样适用此规则
非严格模式下:赋值被忽略,不报错
这是容易被忽视的关键点:行为完全静默。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
-
obj.x = 2不会改变原值,也不抛异常,返回值是2(赋值表达式的右值),但obj.x仍为1 - 这种“看似成功实则失效”的行为容易引发隐蔽 bug,尤其在调试或链式赋值场景中
- 注意:全局变量声明(
var/let/const)不受此影响;只有通过Object.defineProperty或Object.freeze等方式设置的属性才受writable控制
freeze 和 seal 对 writable 的隐式影响
Object.freeze(obj) 会将所有自有属性的 writable 设为 false,且 configurable 也设为 false;Object.seal(obj) 则只冻结 configurable,但默认保留原有 writable 状态。
- 因此
freeze后任何属性赋值在严格模式下必报错,非严格模式下静默失败 -
seal不等于freeze:如果某个属性原本writable: true,seal后仍可修改值(只是不能再删或重定义) - 可通过
Object.getOwnPropertyDescriptor(obj, 'prop')检查当前writable实际值
如何安全地检测并应对不可写属性
不能依赖“赋值后检查值是否变化”来判断(因为非严格模式下值不变但无提示),推荐显式检测:
- 用
Object.getOwnPropertyDescriptor(obj, key)?.writable === false预判 - 封装赋值逻辑时,加
if (descriptor && !descriptor.writable)提前拒绝或记录警告 - 开发阶段开启严格模式 + ESLint 规则(如
no-fallthrough、no-unused-vars)辅助识别潜在静默失败
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










