Object.freeze方法详解与使用技巧
偷偷努力,悄无声息地变强,然后惊艳所有人!哈哈,小伙伴们又来学习啦~今天我将给大家介绍《JavaScript中Object.freeze用法详解》,这篇文章主要会讲到等等知识点,不知道大家对其都有多少了解,下面我们就一起来看一吧!当然,非常希望大家能多多评论,给出合理的建议,我们一起学习,一起进步!
Object.freeze() 在 JavaScript 中用于冻结对象,使其不可修改,包括添加、删除属性或更改属性特性。1. 它仅执行浅冻结,嵌套对象仍可被修改;2. 与 const 不同,它冻结对象内容而非变量绑定;3. 比 Object.seal() 和 Object.preventExtensions() 更严格,禁止任何修改;4. 适用于配置对象、状态管理、公共接口等需不可变性的场景;5. 需注意严格模式下修改会抛出错误、性能开销及无法解冻等限制。
Object.freeze()
在 JavaScript 中用于冻结一个对象,使其不能再被修改。这意味着你不能添加新属性、删除现有属性、改变现有属性的可枚举性、可配置性或可写性,也不能重新分配现有属性的值,甚至不能改变它的原型。它提供了一种简单直接的方式来创建不可变的对象。

解决方案
要冻结一个对象,你只需要将它作为参数传递给 Object.freeze()
方法。该方法会返回被冻结的对象本身。
const config = { apiBaseUrl: 'https://api.example.com', timeout: 5000, debugMode: false }; Object.freeze(config); // 尝试修改,在严格模式下会抛出 TypeError,非严格模式下会静默失败 try { config.apiBaseUrl = 'https://api.new-example.com'; // 尝试修改现有属性 config.newProperty = 'value'; // 尝试添加新属性 delete config.timeout; // 尝试删除属性 } catch (e) { console.error("修改冻结对象失败:", e.message); } console.log(config); // 输出:{ apiBaseUrl: 'https://api.example.com', timeout: 5000, debugMode: false } // 证明对象内容未被改变
当一个对象被冻结后:

- 它的属性值不能被修改(除非是引用类型,后面会讲到)。
- 不能添加新的属性。
- 不能删除现有的属性。
- 不能改变属性的特性(如
writable
,configurable
)。 - 不能改变对象的原型。
Object.freeze
真的能让对象“纹丝不动”吗?理解其“浅冻结”的边界
第一次接触 Object.freeze
的时候,我曾天真地以为它能把一个对象里里外外、彻彻底底地锁死,就像一个密封的保险箱。但实际使用后才发现,它其实是个“浅冻结”。这意味着 Object.freeze()
只作用于对象本身及其直接属性,如果这些直接属性的值是另一个对象(或者数组,数组在 JavaScript 中也是对象),那么这些嵌套的对象或数组本身是 不会 被冻结的。它们的内部属性仍然可以被修改。
这就像你把一个装着几本书的箱子锁起来,箱子本身不能被打开、添加或移除书,但如果你箱子里有一本书是活页的,你可以随意翻动活页,甚至增删活页的内容。箱子是冻结的,但箱子里的“活页书”却不是。

const userProfile = { name: '张三', settings: { theme: 'dark', notifications: true }, roles: ['admin', 'editor'] }; Object.freeze(userProfile); console.log("冻结后的userProfile:", userProfile); // 尝试修改顶级属性(会失败) try { userProfile.name = '李四'; } catch (e) { console.error("修改顶级属性失败:", e.message); } // 尝试修改嵌套对象属性(会成功!) userProfile.settings.theme = 'light'; userProfile.settings.notifications = false; // 尝试修改嵌套数组元素(会成功!) userProfile.roles.push('viewer'); userProfile.roles[0] = 'super_admin'; console.log("修改嵌套属性后的userProfile:", userProfile); /* 输出: { name: '张三', settings: { theme: 'light', notifications: false }, // settings内部被修改了 roles: [ 'super_admin', 'editor', 'viewer' ] // roles内部被修改了 } */
从上面的例子可以看出,userProfile
对象本身是冻结的,你不能直接给它添加 age
属性或者删除 name
属性。但 settings
和 roles
这两个嵌套对象(和数组)并没有被冻结,它们的内部属性和元素仍然可以被修改。
如果你需要一个真正的深度冻结,你需要递归地遍历对象的每一个属性,并对所有嵌套的对象或数组都调用 Object.freeze()
。当然,你也可以借助一些库(如 lodash.clonedeep
然后 Object.freeze
,或者专门的不可变数据结构库)来实现。
Object.freeze
与 const
、Object.seal
、Object.preventExtensions
有何不同?选择合适的“冻结”姿态
JavaScript 提供了几种不同的方式来限制对象的修改,它们各有侧重,就像给对象穿上不同厚度的盔甲。理解它们的区别,能帮助你选择最符合需求的“冻结”姿态。
const
关键字:const
关键字用于声明一个常量。它确保变量的绑定不能被重新赋值。但请注意,const
限制的是变量本身,而不是变量指向的对象内容。const myObject = { a: 1 }; myObject.a = 2; // 允许,因为修改的是对象内部 console.log(myObject); // { a: 2 } // myObject = { b: 2 }; // 报错:TypeError: Assignment to constant variable.
const
只是说myObject
这个变量永远指向同一个内存地址,但这个地址里的内容是可以变化的(除非内容本身是原始值)。Object.preventExtensions()
: 这个方法阻止向对象添加新的属性。但现有属性的值可以修改,也可以删除。const obj1 = { a: 1, b: 2 }; Object.preventExtensions(obj1); obj1.a = 3; // 允许,修改现有属性 delete obj1.b; // 允许,删除现有属性 // obj1.c = 4; // 报错:TypeError: Cannot add property c, object is not extensible console.log(obj1); // { a: 3 }
它就像给对象加了一层“不扩容”的限制,但已有的空间可以随意使用或清空。
Object.seal()
:Object.seal()
比Object.preventExtensions()
更严格。它不仅阻止添加新属性(像preventExtensions
),还阻止删除现有属性。但与Object.freeze()
不同的是,现有属性的值 可以 被修改。const obj2 = { x: 10, y: 20 }; Object.seal(obj2); obj2.x = 30; // 允许,修改现有属性 // obj2.z = 40; // 报错:TypeError: Cannot add property z, object is not extensible // delete obj2.y; // 报错:TypeError: Cannot delete property 'y' of #<Object> console.log(obj2); // { x: 30, y: 20 }
你可以把
Object.seal()
理解为“密封”:不能加新东西,也不能扔掉旧东西,但旧东西里面的内容可以调整。Object.freeze()
: 这是最严格的。它在Object.seal()
的基础上,进一步阻止了现有属性值的修改。简单来说,Object.freeze()
=Object.preventExtensions()
+ 阻止删除属性 + 阻止修改属性值 + 阻止修改属性特性(如可写性、可配置性)+ 阻止修改原型。const obj3 = { key: 'value' }; Object.freeze(obj3); // obj3.key = 'newValue'; // 报错:TypeError: Cannot assign to read only property 'key' of object '#<Object>' // obj3.another = 'something'; // 报错:TypeError: Cannot add property another, object is not extensible // delete obj3.key; // 报错:TypeError: Cannot delete property 'key' of #<Object> console.log(obj3); // { key: 'value' }
它就像给对象上了最厚的锁,一旦锁上,什么都不能动。
总结选择:
const
: 只是保证变量名不重新指向,对象内容可变。Object.preventExtensions()
: 阻止添加新属性,其他随意。Object.seal()
: 阻止添加/删除属性,但允许修改现有属性值。Object.freeze()
: 阻止添加/删除/修改所有属性(值、特性),提供最严格的不可变性(浅层)。
选择哪种方式,取决于你对对象不可变性的需求程度。如果你只是想防止意外地给对象添加新属性,preventExtensions
就够了。如果想确保对象结构稳定(不能增删属性),但内容可以更新,就用 seal
。而如果你需要一个完全只读的对象(至少在浅层),那么 freeze
就是你的首选。
什么时候该用 Object.freeze
?场景、陷阱与性能考量
Object.freeze
虽然强大,但并非万能药,也不是在所有场合都适用。我个人倾向于在那些“只读”的数据结构上果断使用它,比如一些全局配置或者纯粹的数据常量。
典型应用场景:
配置对象或常量: 当你的应用有一些在运行时不应该被修改的配置信息时,
Object.freeze
是一个绝佳的选择。比如 API 地址、错误码映射、用户权限常量等。const APP_CONFIG = Object.freeze({ API_URL: '/api/v1', MAX_RETRIES: 3, DEFAULT_LOCALE: 'en-US' }); // 尝试修改会报错或静默失败 // APP_CONFIG.API_URL = '/api/v2';
这能有效防止开发过程中不经意的修改导致难以追踪的 bug。
状态管理中的不可变性: 在像 Redux 这样的状态管理库中,强调状态的不可变性。虽然通常是通过返回新对象而不是直接修改来实现,但对返回的新状态对象进行
Object.freeze
可以提供额外的保障,确保任何尝试直接修改状态的操作都能被及时发现(在严格模式下抛出错误)。function userReducer(state = {}, action) { switch (action.type) { case 'SET_USER_NAME': // 返回新对象,并冻结 return Object.freeze({ ...state, name: action.payload }); default: return state; } }
共享模块或库的公共接口: 如果你开发一个库或模块,并希望暴露一些公共对象,但又不希望外部代码修改它们,可以使用
Object.freeze
来保护这些对象。这能增强代码的健壮性和可预测性。优化性能(部分场景): JavaScript 引擎在处理冻结对象时,有时可以进行一些内部优化,因为它知道这些对象不会再改变。但这通常是微观优化,对于大多数应用而言,性能提升不是使用
Object.freeze
的主要驱动力,其主要价值在于不可变性带来的代码可维护性和可预测性。
潜在的陷阱与注意事项:
浅冻结的陷阱: 这是最常见的误解和错误来源,前面已经详细讨论过。如果你的对象有嵌套结构,
Object.freeze
只冻结了顶层,嵌套的对象仍然是可变的。如果你需要深度冻结,必须手动递归处理或使用辅助函数。严格模式与非严格模式的行为差异: 在严格模式下,尝试修改一个冻结对象会抛出
TypeError
。这对于调试和发现问题非常有帮助。但在非严格模式下,这些尝试会静默失败,不会有任何错误提示,这使得问题难以发现。因此,强烈建议在项目中使用严格模式。性能考量: 尽管
Object.freeze
本身很快,但如果你需要对非常大或频繁创建的复杂嵌套对象进行深度冻结,递归遍历和复制可能会带来一定的性能开销。在这些极端情况下,可能需要权衡不可变性的需求与性能的优先级,或者考虑使用专门的不可变数据结构库(如 Immutable.js 或 Immer),它们通常有更优的性能表现。无法解冻:
Object.freeze
是一个单向操作,一旦对象被冻结,就没有内置的方法可以“解冻”它。如果你需要一个冻结对象的修改版本,你必须先创建一个它的深拷贝,然后修改这个拷贝。
总的来说,Object.freeze
是一个非常有用的工具,它能够有效地强制执行对象的不可变性,从而提高代码的健壮性和可预测性。但在使用时,务必清楚其“浅冻结”的特性,并在严格模式下使用,以充分利用其错误提示机制。
今天关于《Object.freeze方法详解与使用技巧》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!

- 上一篇
- 电脑黑屏只有鼠标怎么办

- 下一篇
- PHPCMS数据优化技巧分享
-
- 文章 · 前端 | 5小时前 |
- HTML如何设置网页编码?meta标签详解
- 134浏览 收藏
-
- 文章 · 前端 | 5小时前 |
- JavaScript二维数组查找方法详解
- 453浏览 收藏
-
- 文章 · 前端 | 5小时前 |
- screen对象详解:获取屏幕信息的实用方法
- 155浏览 收藏
-
- 文章 · 前端 | 5小时前 |
- p标签是什么元素?CSS中p标签详解
- 364浏览 收藏
-
- 文章 · 前端 | 5小时前 |
- em标签在网页设计中用于强调文本,语义上表示内容需要被特别注意或重读,增强文字的语气和重点。
- 368浏览 收藏
-
- 文章 · 前端 | 5小时前 |
- CSS设置数据空状态样式方法
- 496浏览 收藏
-
- 文章 · 前端 | 5小时前 | html JavaScript 用户体验 撤销功能 操作历史
- HTML需支持撤销功能,提升用户体验与操作安全
- 433浏览 收藏
-
- 文章 · 前端 | 5小时前 |
- JS模块化导入导出详解与应用
- 265浏览 收藏
-
- 文章 · 前端 | 5小时前 |
- JavaScript数组values方法详解
- 247浏览 收藏
-
- 文章 · 前端 | 5小时前 |
- JavaScript事件循环优化动画性能
- 302浏览 收藏
-
- 文章 · 前端 | 5小时前 |
- Sass/LessCSS嵌套实用技巧分享
- 448浏览 收藏
-
- 文章 · 前端 | 5小时前 |
- CSS锚点高亮技巧分享
- 451浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- AI歌曲生成器
- AI歌曲生成器,免费在线创作,简单模式快速生成,自定义模式精细控制,多种音乐风格可选,免版税商用,让您轻松创作专属音乐。
- 18次使用
-
- MeloHunt
- MeloHunt是一款强大的免费在线AI音乐生成平台,让您轻松创作原创、高质量的音乐作品。无需专业知识,满足内容创作、影视制作、游戏开发等多种需求。
- 18次使用
-
- 满分语法
- 满分语法是一款免费在线英语语法检查器,助您一键纠正所有英语语法、拼写、标点错误及病句。支持论文、作文、翻译、邮件语法检查与文本润色,并提供详细语法讲解,是英语学习与使用者必备工具。
- 29次使用
-
- 易销AI-专为跨境
- 易销AI是专为跨境电商打造的AI营销神器,提供多语言广告/产品文案高效生成、精准敏感词规避,并配备定制AI角色,助力卖家提升全球市场广告投放效果与回报率。
- 30次使用
-
- WisFile-批量改名
- WisFile是一款免费AI本地工具,专为解决文件命名混乱、归类无序难题。智能识别关键词,AI批量重命名,100%隐私保护,让您的文件井井有条,触手可及。
- 30次使用
-
- 优化用户界面体验的秘密武器:CSS开发项目经验大揭秘
- 2023-11-03 501浏览
-
- 使用微信小程序实现图片轮播特效
- 2023-11-21 501浏览
-
- 解析sessionStorage的存储能力与限制
- 2024-01-11 501浏览
-
- 探索冒泡活动对于团队合作的推动力
- 2024-01-13 501浏览
-
- UI设计中为何选择绝对定位的智慧之道
- 2024-02-03 501浏览