前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库Object.preventExtensions 扩展性判断 isExtensible
JavaScript对象与原型

Object.preventExtensions() 之后还能给对象加属性吗?怎么判断?

不能加了。Object.preventExtensions(obj) 之后,新增属性在非严格模式下静默失败,严格模式下抛 TypeError。但已有属性照样能改、能删。判断用 Object.isExtensible(obj),返回 false 就说明不可扩展。

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

三级限制,从松到紧

  1. Object.preventExtensions不能加属性,能改能删
  2. Object.seal不能加也不能删,已有属性的值还能改
  3. Object.freeze不能加、不能删、不能改,只冻结第一层

不可扩展的对象连原型都不能换了,Object.setPrototypeOf 会抛 TypeError。但原型对象本身没被锁,往原型上加方法,这个对象照样能通过继承用到。

核心回答

先记住这个答案

Object.preventExtensions(obj) 把对象标记为不可扩展,之后不能再新增属性。非严格模式下写 obj.newKey = 1 什么也不会发生,严格模式下会抛 TypeError。已有的属性不受影响,可以改值,也可以 delete。这个操作是单向的,没有办法恢复成可扩展。判断用 Object.isExtensible(obj),普通对象默认返回 true,处理过之后返回 false。

  • 只禁止新增属性,修改和删除都不受影响
  • 严格模式下新增抛 TypeError,非严格静默失败
  • 操作不可逆,也不能再修改对象的原型
  • 禁止新增属性,但还能改现有属性

看代码:能改能删,就是不能加

下面对一个普通对象调用 preventExtensions,分别试试新增、修改、删除。

新增静默失败,修改和删除正常JavaScript
const user = { name: 'Tom', age: 18 }
Object.preventExtensions(user)

user.email = 'a@b.com' // 非严格模式下静默失败,不报错
user.age = 20 // 修改已有属性,没问题
delete user.name // 删除也没问题
console.log(JSON.stringify(user), Object.isExtensible(user))

try {
  Object.defineProperty(user, 'email', { value: 'x' }) // 换个方式加也不行
} catch (e) {
  console.log(e.name)
}
console.log(Object.isSealed(user), Object.isFrozen(user))
查看输出与解释
{"age":20} false
TypeError
false false

第一行能看出 email 没加上,age 改了,name 删了。第二行说明不可扩展是对象本身的状态,不管是赋值还是 defineProperty,只要是新增属性都会被拦下,而且 defineProperty 不管严格模式与否都会抛错。第三行说明它只是最松的一级,还算不上密封或冻结,因为属性依然可删、可改。

它和 seal、freeze 是什么关系

可以把这三个方法看成逐级加码。preventExtensions 只关上「新增」这扇门;seal 在此基础上把所有属性的 configurable 设成 false,于是也不能删了;freeze 再把所有数据属性的 writable 设成 false,连值都不能改。

所以被 seal 或 freeze 的对象,Object.isExtensible 也一定返回 false。反过来不成立,不可扩展的对象不一定是密封的。有个特例很适合在面试里提:空对象被 preventExtensions 之后,Object.isSealed 和 Object.isFrozen 都返回 true,因为它没有任何属性可以删或改,条件自然都满足。

原型也被锁住了

不可扩展除了不能加属性,还有一条限制:不能再修改对象的原型。调用 Object.setPrototypeOf(obj, other) 会抛 TypeError,除非传的就是它当前的原型。

但这把锁只锁对象自己。它的原型对象还是可扩展的,往 Object.prototype 或类的原型上加方法,这个对象通过原型链照样能调用到。所以 preventExtensions 不能当作「对象的能力从此固定」来用。

回答前,多想一步

容易答错的地方

以为 preventExtensions 会让属性只读
不会。它只管新增,已有属性的 writable 和 configurable 一点没变。要只读得用 freeze,或者用 defineProperty 把单个属性设成 writable: false。
以为可以再调一个方法恢复
没有 Object.allowExtensions 这种方法。不可扩展是单向的,需要可扩展的版本只能复制一份,比如 { ...obj },新对象是可扩展的。
忽略严格模式的差别
同一句 obj.x = 1,在模块或 class 里是严格模式,会直接抛错;放在普通脚本里就静默失败。线上出现「属性怎么没加上也不报错」,多半是这个原因。
试着用自己的话回答

面试官还会怎么问?

对原始值调用 Object.isExtensible 会怎样?

ES2015 以后不会报错,原始值被当作不可扩展的对象,返回 false。Object.preventExtensions(1) 也不报错,原样返回 1。但 Reflect.preventExtensions(1) 会抛 TypeError,Reflect 的方法要求传对象。

数组被 preventExtensions 后能 push 吗?

不能。push 本质是在新的索引上新增属性,会抛 TypeError,规范规定 push 内部写入失败时一律抛错,和代码是否严格模式无关。但 pop 可以,因为删除元素是允许的。

实际项目里什么时候用它?

用得不多。常见场景是给配置对象、插件上下文加一层保护,防止使用方拼错属性名却不自知。更常见的做法是直接用 Object.freeze,或者在开发环境用 Proxy 拦截未知属性并报警。

从一道题,走向一组知识

把知识连起来

对象与原型

call、apply、bind 有什么区别?各自什么时候用?

call、apply、bind 决定方法调用时 this 指向哪个对象,是对象方法之外另一块常考的基础。

对象与原型

Object.getPrototypeOf 和 Object.setPrototypeOf 现在还该用吗?

不可扩展的对象不能再换原型,Object.setPrototypeOf 会直接抛错,两题正好接上。

参考资料

  • JavaScript:对象与原型参考资料

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

本题目录
  1. 先记住这个答案
  2. 看代码:能改能删,就是不能加
  3. 它和 seal、freeze 是什么关系
  4. 原型也被锁住了
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

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

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