JavaScript的Object.freeze方法是什么?怎么用?

object.freeze 是 javascript 中用于冻结对象的方法,它阻止添加、删除或修改对象的顶层属性,但对嵌套对象无效。1. 它接收一个对象并返回被冻结的对象;2. 冻结后,属性不可变,严格模式下修改会抛出错误;3. 实现的是浅冻结,嵌套对象仍可被修改。应用场景包括防止配置对象被篡改、提升代码可预测性和调试效率。与 object.seal 和 object.preventextensions 相比,freeze 最严格,seal 不允许增删属性但可修改值,preventextensions 仅阻止新增属性。实现深冻结需递归冻结所有嵌套对象,并注意处理循环引用问题。

JavaScript的Object.freeze方法是什么?怎么用?

Object.freeze 是 JavaScript 提供的一个方法,它能让一个对象变得“冻结”,这意味着你不能再添加新的属性、删除已有属性、修改属性的枚举性、可配置性或写入性,也无法改变其原型。简单来说,一旦对象被冻结,它就不能再被改变了,至少是其第一层属性。

JavaScript的Object.freeze方法是什么?怎么用?

Object.freeze() 方法接收一个对象作为参数,并返回这个被冻结的对象。它的核心作用就是阻止对目标对象进行任何修改。当你尝试对一个冻结的对象进行添加、删除或修改属性的操作时,在严格模式下会抛出 TypeError 错误,在非严格模式下则会静默失败。需要特别注意的是,Object.freeze 实现的是浅冻结。这意味着如果一个对象内部包含其他对象(比如嵌套对象或数组),这些内部的对象本身并不会被冻结,它们仍然是可变的。这是我个人在使用时经常需要注意的一个点,因为有时候我们期望的是深冻结,但 freeze 并不提供这个功能。

const user = {  name: '张三',  age: 30,  address: {    city: '北京',    zip: '100000'  },  hobbies: ['阅读', '编程']};Object.freeze(user);// 尝试修改冻结对象的属性user.name = '李四'; // 无效,严格模式下会报错console.log(user.name); // 输出 '张三'// 尝试添加新属性user.gender = '男'; // 无效console.log(user.gender); // 输出 undefined// 尝试删除属性delete user.age; // 无效console.log(user.age); // 输出 30// 尝试修改嵌套对象的属性(浅冻结的体现)user.address.city = '上海'; // 有效!console.log(user.address.city); // 输出 '上海'// 尝试修改嵌套数组的元素user.hobbies.push('旅行'); // 有效!console.log(user.hobbies); // 输出 ['阅读', '编程', '旅行']

这个例子很直观地展示了 freeze 的浅层特性。对于 user 对象本身,它的直接属性被锁死了,但 user.addressuser.hobbies 内部的内容,还是可以动的。这在处理复杂数据结构时,确实需要多想一步。

立即学习“Java免费学习笔记(深入)”;

JavaScript的Object.freeze方法是什么?怎么用?

为什么我们需要冻结对象?它在实际开发中有哪些应用场景?

从我个人的经验来看,冻结对象最直接的价值在于提供数据不可变性。在很多复杂的应用中,尤其是涉及到状态管理或者共享数据时,我们经常会遇到数据被意外修改导致的问题,调试起来非常头疼。Object.freeze 提供了一个简单的机制来防止这种意外。

想象一下,你有一个配置对象,它定义了整个应用的常量或者某个模块的默认设置。如果这个配置对象在应用的某个角落被不小心修改了,可能会导致意想不到的行为。通过 Object.freeze 对其进行冻结,可以有效避免这种“运行时篡改”。

JavaScript的Object.freeze方法是什么?怎么用?

// 示例:冻结配置对象const APP_CONFIG = Object.freeze({  API_BASE_URL: 'https://api.example.com',  TIMEOUT_MS: 5000,  DEBUG_MODE: false});// 尝试修改配置// APP_CONFIG.API_BASE_URL = 'http://localhost:3000'; // 严格模式下会报错,有效防止修改// 在函数中传递冻结对象作为参数,确保其不会被函数内部修改function processData(config) {  // config.DEBUG_MODE = true; // 无法修改  console.log('Processing data with config:', config.API_BASE_URL);}processData(APP_CONFIG);

此外,在一些函数式编程的范式中,不可变数据是核心理念。虽然 Object.freeze 只是一个浅层实现,但它至少能保证对象顶层属性的稳定。这对于构建更可预测、更易于测试的代码库非常有帮助。当你在调试一个bug,发现某个数据结构的值不对劲时,如果知道它是被冻结的,至少可以排除掉“被意外修改”这个可能性,缩小排查范围。这种确定性,在项目复杂起来的时候,价值真的很大。

Object.freeze与Object.seal、Object.preventExtensions有什么区别

这三个方法都与对象的“可变性”有关,但它们提供的限制程度是不同的,就像是给对象上锁,但锁的级别不一样。

Object.preventExtensions(): 这是最宽松的限制。它仅仅是阻止向对象添加新的属性。你仍然可以删除现有属性,也可以修改现有属性的值、枚举性、可配置性或写入性。

const obj1 = { a: 1 };Object.preventExtensions(obj1);obj1.b = 2; // 无效console.log(obj1.b); // undefineddelete obj1.a; // 有效console.log(obj1.a); // undefined// obj1.a = 10; // 即使被删除了,这里再赋值也无效,因为preventExtensions后不能添加

这里有个小陷阱,如果属性已经被删除了,再尝试赋值,那其实是尝试添加新属性,所以也是无效的。

Object.seal(): 比 preventExtensions 更进一步。它不仅阻止添加新属性,还阻止删除现有属性。但你仍然可以修改现有属性的值。属性的可配置性(configurable)会被设置为 false,这意味着你不能再删除它们,也不能改变它们的特性(比如从可写变为只读)。

const obj2 = { a: 1, b: 2 };Object.seal(obj2);obj2.c = 3; // 无效delete obj2.a; // 无效obj2.b = 20; // 有效console.log(obj2.b); // 20

在我看来,seal 就像是把对象的“形状”固定下来了,但里面的内容还是可以变的。

Object.freeze(): 这是最严格的。它在 Object.seal 的基础上,进一步阻止了修改现有属性的值。所有属性的 writableconfigurable 都会被设置为 false。这意味着,你不能添加、删除或修改任何属性。

const obj3 = { a: 1, b: 2 };Object.freeze(obj3);obj3.c = 3; // 无效delete obj3.a; // 无效obj3.b = 20; // 无效console.log(obj3.b); // 2

总的来说,可以想象成一个渐进的过程:

preventExtensions: 不能增加新房间。seal: 不能增加新房间,也不能拆除旧房间,但房间里的家具可以换。freeze: 不能增加新房间,不能拆除旧房间,连房间里的家具都不能换了。

理解这些区别,在选择如何保护对象时,就能做出更合适的决策。我发现很多人容易混淆这几个,但其实它们各自有明确的适用场景。

如何实现一个“深冻结”功能?

前面提到了 Object.freeze 是浅冻结,这在处理包含嵌套对象或数组的数据时,确实是个痛点。如果我真的需要整个数据结构都不可变,那么就需要自己动手实现一个“深冻结”函数。这通常涉及到递归地遍历对象的所有属性。

实现深冻结的核心思路是:遍历对象的所有属性,如果某个属性的值也是一个对象(且不是 null,也不是函数、日期、RegExp等不可冻结的内置对象),那么就递归地对这个内部对象也进行冻结。

function deepFreeze(obj) {  // 检查对象是否为null或非对象类型,如果是,则直接返回,因为它们无法被冻结  if (obj === null || typeof obj !== 'object' || obj instanceof Date || obj instanceof RegExp || typeof obj === 'function') {    return obj;  }  // 获取对象的所有属性名  const propNames = Object.getOwnPropertyNames(obj);  // 遍历所有属性  for (const name of propNames) {    const value = obj[name];    // 如果属性值是一个对象,并且它不是null,就递归地调用deepFreeze    if (typeof value === 'object' && value !== null) {      deepFreeze(value);    }  }  // 最后冻结当前对象  return Object.freeze(obj);}// 示例使用const complexObj = {  id: 1,  data: {    name: '产品A',    details: {      price: 100,      currency: 'USD'    }  },  tags: ['电子产品', '新上市'],  config: null, // null 不会报错  method: () => console.log('hello') // 函数也不会报错};const frozenComplexObj = deepFreeze(complexObj);// 尝试修改顶层属性frozenComplexObj.id = 2;console.log(frozenComplexObj.id); // 1// 尝试修改嵌套对象属性frozenComplexObj.data.name = '产品B';console.log(frozenComplexObj.data.name); // '产品A'// 尝试修改更深层嵌套对象属性frozenComplexObj.data.details.price = 120;console.log(frozenComplexObj.data.details.price); // 100// 尝试修改数组元素frozenComplexObj.tags.push('热销');console.log(frozenComplexObj.tags); // ['电子产品', '新上市']// 尝试修改函数或nullfrozenComplexObj.config = {}; // 无效frozenComplexObj.method = () => console.log('world'); // 无效

实现深冻结时,需要注意循环引用(circular references)的问题。如果对象A引用了对象B,而对象B又引用了对象A,那么简单的递归可能会导致无限循环。不过,对于大多数实际应用场景,这种问题不常见,或者可以通过额外的机制(比如记录已访问过的对象)来避免。我这里提供的 deepFreeze 版本没有处理循环引用,在实际生产环境中,如果数据结构可能存在循环引用,需要引入一个 Set 来记录已经处理过的对象,避免无限递归

以上就是JavaScript的Object.freeze方法是什么?怎么用?的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1509547.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
BOM中如何操作浏览器的滚动条?
上一篇 2025年12月20日 05:30:16
Shopify教程:高效筛选并展示特定Collection中的产品
下一篇 2025年12月20日 05:30:23

相关推荐

  • 如何在MiniToolMovieMaker中编辑AI视频?免费AI视频剪辑的教程

    如何在MiniToolMovieMaker中编辑AI视频?免费AI视频剪辑的教程如何在MiniToolMovieMaker中编辑AI视频?免费AI视频剪辑的教程如何在MiniToolMovieMaker中编辑AI视频?免费AI视频剪辑的教程如何在MiniToolMovieMaker中编辑AI视频?免费AI视频剪辑的教程

    MiniTool MovieMaker虽无AI生成功能,但可高效编辑AI生成的MP4、MOV等格式视频或图片序列。通过导入素材后,利用其剪辑、过渡、滤镜、文字、音频处理等功能,实现AI片段的精剪、色彩统一、无缝衔接与风格化输出。支持主流视频、图片及音频格式,兼容性好,适合个人创作者进行AI内容后期整…

    2026年9月22日 用户投稿
    500
  • VSCode如何调试JavaScript代码 VSCode调试功能的实战技巧

    要在vscode中调试javascript,首先需设置断点、配置launch.json文件、选择合适的调试环境并启动调试会话;2. launch.json至关重要,常见陷阱包括program路径错误、type类型不匹配、cwd设置不当、混淆launch与attach模式以及source map配置缺…

    2026年9月22日
    000
  • 华为MateView 32对决戴尔U3223QE:专业级显示器的色彩与护眼之战,为谁的眼睛买单更值?

    华为MateView 32侧重生态协同与竖屏效率,戴尔U3223QE强在高对比度面板与扩展性,选择取决于设备生态及工作需求。 华为MateView 32和戴尔U3223QE都是定位高端的专业显示器,但设计思路和侧重点有所不同。选哪款更“值”,关键看你的工作场景、设备生态和对特定功能的重视程度。它们在…

    2026年9月22日
    000
  • Linux内核13-进程切换

    进程切换,也称为任务切换、上下文切换或任务调度,本文将探讨linux内核中进程切换的实现。我们首先理解几个关键概念。 1.1 硬件上下文 每个进程都有自己的地址空间,但所有进程共享CPU寄存器。因此,在恢复进程执行前,内核必须确保挂起时的寄存器值被重新加载到CPU寄存器中。 这些需要加载到CPU寄存…

    2026年9月22日
    200
  • 如何修改MySQL的默认端口号?

    如何修改MySQL的默认端口号?如何修改MySQL的默认端口号?如何修改MySQL的默认端口号?如何修改MySQL的默认端口号?

    修改mysql默认端口号需编辑配置文件,核心步骤为:1.定位my.cnf或my.ini文件;2.在[mysqld]段落中修改或添加port参数;3.保存后重启mysql服务。更改端口主要出于避免冲突、提升安全性和适应网络策略考虑。连接时需在客户端工具或代码中指定新端口,如命令行加-p参数、编程语言连…

    2026年9月22日 用户投稿
    1200
  • 抖音短视频如何选择合适的BGM?音乐对流量影响有多大?

    抖音短视频如何选择合适的BGM?音乐对流量影响有多大?抖音短视频如何选择合适的BGM?音乐对流量影响有多大?抖音短视频如何选择合适的BGM?音乐对流量影响有多大?抖音短视频如何选择合适的BGM?音乐对流量影响有多大?

    选对bgm能显著提升抖音视频流量。bgm不仅烘托氛围,还影响算法推荐和用户停留;平台通过音乐判断视频类型与受众,节奏感强的音乐提高完播率,增强情绪共鸣促进互动;选音乐需结合内容调性、热门趋势与受众喜好,如搞笑类配明快音乐、美食类用温馨轻音乐,关注热榜与同类账号参考;常见误区包括音量过大、风格不符、盲…

    2026年9月22日 用户投稿
    100
  • 在 Linux 中如何强制停止进程?kill 和 killall 命令有什么区别?

    在日常工作中,您可能会遇到两个用于在 linux 中强制结束程序的命令:kill和killall。虽然许多 linux 用户熟悉kill命令,但使用killall命令的人相对较少。尽管这两个命令名称相似且目的相同(终止进程),但它们在使用方式和效果上有显著区别。 那么,kill和killall之间有…

    2026年9月22日
    100
  • 一加Pro系列微信收款语音怎么开启?快速设置支付播报的方法

    首先检查微信内“收款小账本”开启语音播报功能,其次确保手机系统给予微信通知权限、关闭勿扰模式、媒体音量正常,并在电池设置中避免微信后台被限制,同时更新微信至最新版本;若需个性化,可通过系统通知渠道单独设置收款通知的声音与优先级,但无法更换播报音色;使用时注意公共场合隐私保护,务必核对屏幕金额以防误报…

    2026年9月22日
    100
  • 抖音专营店怎么添加直播号?怎么把新开的抖音号添加到专营店里

    随着抖音平台社交属性不断增强,内容生态日益丰富,越来越多电商从业者开始在该平台上开展业务。其中,抖音专营店作为电商布局的重要一环,也吸引了大量商家入驻。那么,如何将直播号加入抖音专营店中,让直播成为店铺引流和销售的新工具呢?接下来的内容将为您详细介绍。 一、为什么要在抖音专营店中添加直播号 提升店铺…

    2026年9月22日
    000
  • 中国联通正式获得开展 eSIM 手机运营服务商用试验的批复

    感谢网友 会弹琴的九号、学士 的线索投递! 10月13日,三大运营商官方微信号相继发布消息,宣告eSIM服务进入新阶段。其中,中国联通于当日上午10:00率先发布推文《抢约!联通eSIM来了!》,动作迅速,展现出强烈的市场积极性;中国移动在傍晚19:29发布《中国移动全面上线eSIM手机办理》;而中…

    2026年9月22日
    200
  • 为什么建议手动定义Java序列化ID

    手动定义serialVersionUID可确保序列化兼容性,避免因类结构变化导致反序列化失败。Java默认生成的ID依赖类名、字段等信息,编译环境或代码微小改动均使其改变,易引发InvalidClassException。显式声明后,可在兼容性变更时主动控制ID更新,保留原ID则允许旧版本读取新对象…

    2026年9月22日
    200
  • mysql怎么使用全文索引 mysql创建全文索引的配置方法

    mysql怎么使用全文索引 mysql创建全文索引的配置方法mysql怎么使用全文索引 mysql创建全文索引的配置方法mysql怎么使用全文索引 mysql创建全文索引的配置方法mysql怎么使用全文索引 mysql创建全文索引的配置方法

    mysql使用全文索引的核心是让数据库像搜索引擎一样理解并高效检索文本内容。1. 创建全文索引:可在建表时或之后通过alter table语句为char、varchar或text字段添加fulltext索引;2. 使用match against查询:支持自然语言模式(自动过滤停用词并按相关性排序)和…

    2026年9月22日 用户投稿
    100
  • VSCode如何通过调试变量监视列表批量追踪数据变化 VSCode变量监视列表批量追踪的新颖技巧​

    VSCode如何通过调试变量监视列表批量追踪数据变化 VSCode变量监视列表批量追踪的新颖技巧​VSCode如何通过调试变量监视列表批量追踪数据变化 VSCode变量监视列表批量追踪的新颖技巧​VSCode如何通过调试变量监视列表批量追踪数据变化 VSCode变量监视列表批量追踪的新颖技巧​VSCode如何通过调试变量监视列表批量追踪数据变化 VSCode变量监视列表批量追踪的新颖技巧​

    vscode中高效批量追踪数据变化的关键是将监视列表用作表达式求值器,而非仅添加单一变量;2. 可在监视列表中添加复杂对象路径(如user.profile.address.city)、计算表达式(如(a + b) * c)、函数调用(如calculatetotal(items))或条件判断(如myv…

    2026年9月22日 用户投稿
    000
  • 如何设置Linux服务超时参数 systemd服务超时配置

    如何设置Linux服务超时参数 systemd服务超时配置如何设置Linux服务超时参数 systemd服务超时配置如何设置Linux服务超时参数 systemd服务超时配置如何设置Linux服务超时参数 systemd服务超时配置

    systemd服务超时参数调整方法包括:1.使用systemctl show查看timeoutstartsec、timeoutstopsec、timeoutsec字段获取当前配置;2.通过systemctl edit编辑unit文件设置timeoutstartsec、timeoutstopsec或t…

    2026年9月22日 用户投稿
    000
  • mysql安装完如何诊断 mysql慢查询分析与优化方法

    要解决 mysql 慢查询问题,首先要开启慢查询日志,其次使用 mysqldumpslow 分析日志,再通过 explain 查看执行计划,最后根据常见优化建议改进 sql 和索引。具体步骤如下:一、修改配置文件或动态开启慢查询日志,并设置阈值和路径;二、使用 mysqldumpslow 工具分析慢…

    2026年9月22日
    100
  • 主板供电相数对CPU超频稳定性的影响:14相 vs. 20相实测

    20相供电主板在超频下表现更稳,实测显示其VRM温度更低、电压波动更小、性能输出更一致,尤其适合极限超频和高负载场景,而14相供电配合优质用料也能满足主流超频需求,普通用户无需盲目追求高相数。 主板供电相数直接影响CPU在高负载和超频状态下的电压稳定性和温度控制。很多人在选择主板时会看到“14相”或…

    2026年9月22日
    200
  • Java中如何区分逻辑错误和系统异常

    系统异常是程序运行中由JVM抛出的RuntimeException,如空指针、数组越界,会导致程序中断并打印堆栈;逻辑错误是程序语法正确但结果不符预期,如条件写反、循环次数错误,不会崩溃但行为异常。两者区别在于是否抛出异常、是否中断执行及调试方式不同,需通过防御性编程、单元测试和日志调试加以防范。 …

    2026年9月22日
    000
  • mysql安装后怎么建表 mysql创建数据表的详细步骤

    mysql安装后怎么建表 mysql创建数据表的详细步骤mysql安装后怎么建表 mysql创建数据表的详细步骤mysql安装后怎么建表 mysql创建数据表的详细步骤mysql安装后怎么建表 mysql创建数据表的详细步骤

    安装完 mysql 后,建表的关键在于先创建数据库并选择使用,然后通过 create table 语句定义表结构。1. 创建数据库:使用 create database mydatabase; 创建数据库;2. 使用数据库:通过 use mydatabase; 选择当前操作的数据库;3. 建表语法:…

    2026年9月22日 用户投稿
    200
  • 夸克浏览器电脑网页版访问入口 夸克官网主页链接地址

    夸克浏览器电脑网页版访问入口是https://www.quark.cn/,用户可直接在浏览器地址栏输入该链接访问,其界面采用极简设计并集成智能搜索、网盘服务与跨设备同步等功能。 立即进入“☞☞☞☞☞点击夸克资源网(永久免费)入口☜☜☜☜☜”; 立即进入“☞☞☞☞☞点击夸克浏览器电脑网页版访问入口☜☜…

    2026年9月22日
    500
  • 抖音小店如何运营?普通人开店选品与推广的实用策略

    抖音小店如何运营?普通人开店选品与推广的实用策略抖音小店如何运营?普通人开店选品与推广的实用策略抖音小店如何运营?普通人开店选品与推广的实用策略抖音小店如何运营?普通人开店选品与推广的实用策略

    新手做抖音小店最现实的问题是没钱投广告和没专业团队,解决方法是抓住选品和推广两个核心环节。一、选品要找市场需求高且利润合理的商品,避开竞争激烈或太冷门的品类,结合多平台数据测试;二、前期重点用“商品卡”推广,通过短视频展示产品使用场景并挂链接引流,成本低且适合测试;三、适当尝试直播积累经验,但不依赖…

    2026年9月22日 用户投稿
    400

发表回复

登录后才能评论
关注微信