JavaScript属性描述符writable对赋值行为的限制
Ja vaScript属性描述符writable对赋值行为的限制

在Ja vaScript的对象世界里,给一个属性加上“只读”锁,听起来是个简单的操作。但你真的了解这把锁的精确作用范围吗?今天,我们就来深入聊聊writable: false这个描述符——它远不止“不能改”那么简单。
核心结论先摆在这里:当一个属性的writable被设为false,直接通过赋值操作符(=)去修改它的值,这条路就走不通了。在严格模式下,浏览器会毫不客气地抛出一个TypeError;而在非严格模式下,它则会选择“静默失败”——代码照常运行,不报错,但属性的值纹丝不动。
writable: false 时的赋值表现
这里有个关键细节需要划重点:writable: false限制的仅仅是常规的赋值操作(obj.prop = newValue)。它并不妨碍你通过Object.defineProperty或Object.defineProperties这些“元编程”工具去修改属性描述符本身。当然,这么做有个大前提:该属性的configurable描述符必须是true。
具体表现,我们可以看几个典型场景:
- 非严格模式:执行
obj.x = 100,控制台风平浪静,但回头检查obj.x,你会发现它还是原来的值。 - 严格模式:同样的
obj.x = 100,会立即触发TypeError: Cannot assign to read only property 'x',赋值被明确拒绝。 - 试图用defineProperty覆盖:直接调用
Object.defineProperty(obj, 'x', { value: 200 })也会失败,除非你同时将writable设为true,或者该属性原本就是configurable: true,允许你先修改描述符。
与 const 声明的区别
很多人容易把writable: false和const声明混淆。其实,它们守护的“阵地”完全不同。
writable: false是对象属性级别的写保护。它锁定的,是某个特定属性的值。而const,是变量(或常量)绑定级别的不可重新赋值。它锁定的,是变量名与那个值(或引用)之间的绑定关系。
举个例子就清楚了:
const obj = { x: 1 };这里,const意味着你不能让obj这个变量名指向另一个对象(比如obj = {}会报错)。但是,obj.x = 2这个操作完全可行——除非x属性本身被设置了writable: false。- 反过来,
Object.defineProperty(obj, 'x', { value: 1, writable: false })一旦执行,那么无论obj本身是用const、let还是var声明的,obj.x = 2这个赋值操作都会被禁止。
简单说,const管的是“装东西的篮子不能换”,而writable: false管的是“篮子里的某个特定物品不能换”。
如何检测和修改 writable 状态
那么,在实际开发中,我们怎么知道一个属性是不是只读的?又有没有办法“解锁”它呢?
答案是肯定的。使用Object.getOwnPropertyDescriptor(obj, 'prop'),这个方法会返回一个描述符对象,里面清清楚楚地列着writable、configurable、enumerable和value的当前状态。
至于修改,关键在于另一个描述符:configurable。它的名字已经说明了一切——它决定了属性的配置是否可被更改。
- 如果
configurable: true,那么恭喜,你可以随时通过Object.defineProperty,将writable从false改回true,从而重新获得赋值权限。 - 但如果
configurable: false,情况就严峻了。这意味着属性被“永久锁定”,它的writable状态(以及其他描述符)再也无法被修改。一个既writable: false又configurable: false的属性,就成了一个真正意义上的“铁板一块”。
常见误用场景
最后,我们来看几个开发者常踩的坑。最大的误解莫过于:以为给一个对象设置几个writable: false的属性,就等于“冻结”了整个对象。
事实远非如此。writable: false的保护是精确到单个属性的。
- 假设对象
obj的属性a是writable: false,那么obj.a = 1会失败。但这丝毫不影响你给对象新增一个属性b(obj.b = 2),或者修改另一个writable: true的属性。 - 如果你想要的是更全面的保护,Ja vaScript提供了更高级的“封印”方法:
Object.preventExtensions(obj):禁止对象添加新属性。
Object.seal(obj):在preventExtensions的基础上,额外将所有现有属性设为configurable: false(但writable为true的属性仍可修改值)。
Object.freeze(obj):这是最高级别的“冻结”。它在seal的基础上,进一步将所有自有数据属性的writable设为false。一个被freeze的对象,其结构(不能增删属性)和内容(不能修改值)都被彻底锁定了。
所以,下次当你需要保护对象数据时,先想清楚:你需要的,究竟是给个别贵重物品上锁(writable: false),还是给整个保险箱贴上封条(Object.freeze)?
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
如何用HTML制作带评分和评论的产品详情区域
构建评分评论模块需兼顾语义化与无障碍访问。评分区使用fieldset与单选按钮实现互斥选择,评论列表采用ol的reversed倒序展示。提交时阻止页面刷新,校验失败保留内容,成功则异步更新列表与平均分。平均分保留一位小数,并通过aria-live确保辅助技术感知动态更新,以保障键盘与屏幕阅读器用户体验。
Django基于主键动态生成文章详情页URL完整教程
在Django项目规划文章详情页URL时,很多开发者会纠结:该用可读性强的slug,还是简单可靠的主键(pk)?如果你的网站内容尚未上线,或你希望彻底摆脱维护slug字段的麻烦,那么将URL从slug切换为pk,无疑是一次一劳永逸的明智选择。 这一过程并不复杂,核心在于同步调整路由、视图和模板三部分
使用BigInt对原始128位UUID进行二进制解析与逻辑运算
在处理全局唯一标识符(UUID)时,我们常常需要深入到其二进制层面进行解析、比较或生成变体。JavaScript 原生的 BigInt 类型,凭借其处理任意精度整数的能力,为直接操作 128 位的 UUID 原始数据提供了可能。不过,这里有个关键前提:BigInt 并不能直接“理解”带连字符的 UU
用new操作符四步模拟实现自定义myNew
要真正掌握 JavaScript 中的 new 操作符,与其死记硬背,不如亲手模拟一遍它的内部实现机制。这个过程能帮助你彻底打通原型、构造函数、this 绑定等核心概念。简单来说,模拟 new 可以拆解为四个清晰的步骤:创建一个继承自构造函数原型的新对象,将构造函数的 this 绑定到这个新对象并执
利用闭包构建偏函数简化多参数API调用
在Python编程中,我们常常面临需要重复调用某个函数,而每次仅少数参数发生变化的情况。此时,偏函数(Partial Application)便能发挥巨大作用——它允许我们预先固定部分参数,生成一个调用时更简洁的新函数。你可能已经使用过functools partial,但你是否思考过它的底层机制究
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
相关攻略
2026-07-05 06:59
2026-07-05 06:58
2026-07-05 06:58
2026-07-05 06:58
2026-07-05 06:58
2026-07-05 06:57
2026-07-05 06:57
2026-07-05 06:57
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

