前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库writable false 严格模式与非严格模式赋值结果
JSJavaScript对象与原型

在严格模式下修改 writable:false 的属性会怎样?非严格模式呢?

严格模式下给 writable:false 的属性赋值会抛出 TypeError;非严格模式(sloppy mode)则静默失败,赋值无效、属性值不变,也不报错。

前端进阶之旅 · 一题精讲更新于 2026.09.05
JavaScript#对象与原型#流处理
先看核心答案读代码示例
理解线索

writable 描述符的写入规则

  1. writable:false禁止通过赋值修改属性的 value
  2. 严格模式非法写入转化为 TypeError 抛出
  3. 非严格模式写入静默无效,不报错也不改值

赋值失败后是否抛错取决于执行写入的代码是否在严格模式,而非定义属性时的环境。

核心回答

先记住这个答案

用 Object.defineProperty 把属性定义为 writable:false 后,普通赋值 obj.x = v 的结果取决于代码是否运行在严格模式。严格模式下该赋值抛出 TypeError;非严格模式下赋值被静默忽略,表达式正常结束,属性保持原值。判断边界是:只有真正执行写操作的代码所处的严格性决定行为,与属性定义时是否严格无关。可用 Object.getOwnPropertyDescriptor 检查 writable,或统一用严格模式加 try/catch 捕获非法写入。

  • 严格模式写不可写属性抛 TypeError
  • 非严格模式静默失败,值保持不变
  • 行为由写入处代码的严格性决定

属性描述符如何拦截写入

JavaScript 中每个对象属性都带有一组描述符:数据属性包含 value、writable、enumerable、configurable。执行 obj.x = v 时,引擎先取得该属性的描述符,若 writable 为 false,内部写入操作返回失败。接下来是否抛错取决于执行赋值语句的代码是否处于严格模式:严格模式把这个失败转化为 TypeError,非严格模式直接丢弃结果。

这种分裂行为源于历史兼容。早期 JavaScript 为了让脚本尽量跑下去,大量错误被设计成静默失败;严格模式是后来加入的受限变体,专门把这类静默错误改成显式异常。因此同一句 obj.x = 9,在 'use strict' 作用域内抛错,在普通脚本里什么都不发生,属性值依旧是原值,也不存在部分写入。

两种模式下赋值 writable:false 属性JavaScript
const obj = {};
Object.defineProperty(obj, "x", { value: 42, writable: false });

function sloppyWrite() {
  obj.x = 9;
  return "sloppy done, x=" + obj.x;
}

function strictWrite() {
  "use strict";
  try {
    obj.x = 9;
    return "no error, x=" + obj.x;
  } catch (e) {
    return e.name + ", x=" + obj.x;
  }
}

console.log(sloppyWrite());
console.log(strictWrite());
console.log(obj.x);
查看输出与解释
sloppy done, x=42
TypeError, x=42
42

同一属性 x,在非严格函数中赋值静默失败,在严格函数中抛出 TypeError,两种情况下 x 都保持 42。可直接在现代浏览器控制台或 Node 环境运行。

配置对象被意外改写的排查

一个 SDK 把默认超时配置定义为不可写:Object.defineProperty(config, 'timeout', { value: 3000, writable: false }),约束是任何业务代码不得改动它。某业务文件未启用严格模式,其中 config.timeout = 500 被静默吞掉,之后请求仍按 3000 毫秒超时,开发者误以为配置生效,排查半天才发现值从未改变。

处理方式是给整个代码库启用严格模式(ES module 默认严格),让同样的误写在测试阶段就抛 TypeError 暴露出来。结果:非法改写从运行期的诡异行为变成启动期即失败的明确错误。可操作判断是:凡是用 defineProperty 锁定的属性,都应假设调用方可能处于非严格环境,因此靠 writable 防篡改的同时,还要靠严格模式或 Reflect.set 的返回值来感知失败。

什么情况下这套规则会失效

第一,writable:false 只阻止修改 value,不阻止用 Object.defineProperty 重新定义该属性;要彻底锁定还需 configurable:false。第二,如果属性在原型链上是不可写数据属性,给实例赋值同名属性同样遵循严格模式规则:严格模式抛错,非严格模式静默失败、不会创建遮蔽属性,这一点常被忽略。

第三,Proxy 可以拦截 set 并返回任意结果,writable 规则不再直接生效;但规范设有不变量:目标对象存在不可配置且不可写的数据属性时,set 陷阱若返回 true 则实际值必须与目标值一致,否则抛 TypeError。代价是 Proxy 场景下不能再用描述符推断写入行为,需要改用 Reflect.set 并检查其布尔返回值来判断成败。

回答前,多想一步

容易答错的地方

以为非严格模式赋值会部分生效
不会。写入要么完整成功要么完全无效,obj.x = 9 静默失败后属性值保持原值,不存在中间状态;可用 Object.getOwnPropertyDescriptor 验证 value 未变。
以为定义属性时开了严格模式就够了
行为由执行赋值语句的代码所在作用域的严格性决定,与 defineProperty 调用处的模式无关。定义处严格、写入处非严格时,写入依然静默失败。
试着用自己的话回答

面试官还会怎么问?

如何在非严格模式下感知写入失败?

使用 Reflect.set(obj, key, value),它返回布尔值表示写入是否成功,对 writable:false 的属性返回 false,借此可以显式处理失败而不依赖异常。

writable:false 和 configurable:false 要一起用吗?

若要属性彻底不可变应同时设置。只有 writable:false 时仍可用 Object.defineProperty 重新定义 value;加上 configurable:false 后重定义会被禁止并抛 TypeError。

对只有 getter 没有 setter 的访问器属性赋值呢?

规则相同:访问器属性缺少 set 时写入失败,严格模式抛 TypeError,非严格模式静默无效。MDN 把不可写数据属性、只读访问器、不可扩展对象新增属性并列为三类写入失败。

从一道题,走向一组知识

把知识连起来

对象与原型

当一个构造函数显式返回一个对象时,new 表达式的结果是什么?如果返回原始值呢?

同属「对象与原型」专题,接着看 构造函数 return 对象或原始值时 new 的结果 在具体场景中的处理方式。

对象与原型

在原型链上查找属性时,JavaScript 的解析顺序是怎样的?

同属「对象与原型」专题,接着看 JavaScript 原型链属性查找顺序 在具体场景中的处理方式。

放回知识体系中复习JavaScript 进阶知识

参考资料

  • Strict mode

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 属性描述符如何拦截写入
  3. 配置对象被意外改写的排查
  4. 什么情况下这套规则会失效
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑