当前位置: 首页 > news >正文

【JavaScript】const 定义的对象禁止修改内部属性

在JavaScript中,使用const声明对象只能确保​​对象引用不被重新赋值​​,而对象的内部属性默认仍可修改。如果我们想要禁止修改内部属性可以使用如下方法:


🔒 ​​1. 使用Object.freeze()冻结对象​

​作用​​:使对象不可扩展、不可删除属性,且属性值不可修改(浅冻结)。

const obj = { name: 'Alice', details: { age: 25 } };
Object.freeze(obj);obj.name = 'Bob';     // 修改失败(严格模式报错)
obj.newProp = 'test'; // 添加失败
delete obj.name;       // 删除失败
console.log(obj);     // 输出原对象 { name: 'Alice', ... }

​局限​​:只能冻结第一层属性,嵌套对象仍可修改(如obj.details.age = 30生效)。


🌳 ​​2. 深度冻结:递归冻结嵌套对象​

通过递归冻结所有层级的属性:

function deepFreeze(obj) {Object.freeze(obj);Object.keys(obj).forEach(key => {if (typeof obj[key] === 'object' && obj[key] !== null) {deepFreeze(obj[key]); // 递归冻结嵌套对象}});
}const user = { profile: { name: 'Alice', settings: { theme: 'dark' } } };
deepFreeze(user);
user.profile.settings.theme = 'light'; // 修改失败
console.log(user.profile.settings.theme); // 仍为 'dark'

​适用场景​​:需完全不可变的配置对象或全局状态。


🛡️ ​​3. 使用Proxy拦截修改操作​

通过Proxy自定义set行为,禁止修改:

const handler = {set(target, key) {throw new Error(`禁止修改属性 ${key}`);// 或静默失败:return true; // 不实际修改}
};const obj = new Proxy({ name: 'Alice' }, handler);
obj.name = 'Bob'; // 抛出错误:禁止修改属性 name

​优点​​:灵活控制修改行为(如仅允许特定条件修改)。


🔐 ​​4. 闭包封装私有变量​

通过闭包隐藏数据,仅暴露访问方法:

function createPerson(name) {let _name = name; // 闭包保护变量return {getName: () => _name,setName: newName => { _name = newName } // 可控修改};
}const person = createPerson('Alice');
console.log(person.getName()); // 'Alice'
person._name = 'Bob'; // 无效(_name不可直接访问)

​适用场景​​:需要封装私有状态且支持受控修改的场景。


🧩 ​​5. TypeScript的readonly修饰符​

在TypeScript中编译时检查:

interface User {readonly name: string;readonly settings: { readonly theme: string }; // 嵌套需手动标记
}const user: User = { name: 'Alice', settings: { theme: 'dark' } };
user.name = 'Bob'; // 编译时报错
user.settings.theme = 'light'; // 编译通过!需额外冻结嵌套对象

​局限​​:仅编译时检查,运行时仍需Object.freeze配合。


⚡ ​​6. 不可变数据结构(ES15+或三方库)​

  • ​ES15 Record/Tuple​​(提案阶段):

    const record = #{ name: 'Alice', age: 30 };
    record.name = 'Bob'; // 运行时报错
    
  • ​Immutable.js库​​:

    const { Map } = require('immutable');
    const data = Map({ name: 'Alice' });
    const newData = data.set('name', 'Bob'); // 返回新对象,原对象不变
    

​优点​​:真正的不可变性,适合复杂状态管理(如Redux)。


💎 ​​方案对比与选型建议​

​方法​​防修改级别​​嵌套支持​​运行时保护​​适用场景​
Object.freeze()浅冻结简单配置对象
deepFreeze深冻结全局配置/需完全不可变的数据
Proxy自定义需动态拦截修改的场景
闭包封装完全私有封装私有状态
TypeScript readonly编译时检查需手动标记大型TS项目
Record/Tuple完全不可变未来ES标准(目前提案阶段)
Immutable.js完全不可变复杂状态管理(如Redux)

⚠️ ​​关键注意事项​

  1. ​严格模式影响​​:Object.freeze在严格模式下修改属性会抛出TypeError,非严格模式静默失败。
  2. ​性能考量​​:频繁深冻结大型对象可能影响性能,可改用不可变库(如Immer)优化。
  3. ​框架兼容性​​:在Vue/React中使用冻结对象时,需注意框架的响应式机制(如Vue无法追踪冻结对象的变化)。

实际项目中,​​深冻结 + TypeScript类型检查​​是最常用组合,兼顾开发体验与运行时安全。对性能敏感场景推荐使用Immutable.jsES Record/Tuple

http://www.dtcms.com/a/303387.html

相关文章:

  • USRP X410 X440 5G及未来通信技术的非地面网络(NTN)
  • Windows10镜像下载
  • 策略路由—PBR
  • laravel chunkById导出数据乱序问题
  • 软件工程:阿里巴巴Java编程手册
  • CCCS作为主要起草人参与《信息技术 智能语音交互系统 第3部分:智能客服》国家标准修订
  • 阿里云 【免费试用】MCP 赋能可视化 OLAP 智能体应用
  • 『 C++ 入门到放弃 』- 哈希表
  • 微积分 | dx / dy 不是比率吗?
  • 《C++继承详解:从入门到理解公有、私有与保护继承》
  • ffmpeg-7.1.1 下载安装 windows 版,MP4 转 m3u8 切片,遇到报错 Unrecognized option ‘vbsf‘的解决办法
  • Linux:理解操作系统
  • 数据结构(动态数组)
  • PyTorch中flatten()函数详解以及与view()和 reshape()的对比和实战代码示例
  • DevOps时代的知识治理革命:Wiki如何成为研发效能的新引擎
  • GPT Agent与Comet AI Aent浏览器对比横评
  • Anaconda创建环境报错:CondaHTTPEFTOT: HTTP 403 FORBIDDEN for url
  • 力扣 之 最小覆盖子串(变长滑动窗口,越短越好)
  • 推客系统全链路架构设计与高并发实践:从CPS分佣到社交裂变
  • ARM双频RFID读写系统的设计
  • 【快捷指令】ios/macos快捷指令如何调用api接口(json请求例子)
  • 从“数字鸿沟”到“数字红利”:智慧养老如何让老人跨越技术门槛
  • MBR和GPT分区的区别
  • C语言-数组:数组(定义、初始化、元素的访问、遍历)内存和内存地址、数组的查找算法和排序算法;
  • 导入Maven项目
  • 解决幻读问题
  • maven 打包报错 process terminated
  • 基于Spring Boot+Vue的吉他社团系统设计和实现(协同过滤算法)
  • 架构师增效指南:飞算JavaAI:需求驱动下的智能微服务拆分与治理
  • 五自由度磁悬浮轴承转子不平衡质量的高性能控制策略全解析