怎样实现javascript对象冻结_javascript中如何防止数据篡改

发布时间 - 2026-01-04 00:00:00    点击率:
Object.freeze() 仅浅冻结对象,嵌套对象仍可修改;深冻结需手动递归实现,注意跳过null、原始值、函数并用WeakMap防循环引用;preventExtensions、seal、freeze防篡改强度逐级增强但均不递归;生产中应慎用freeze,仅适用于配置常量等极少数场景。

Object.freeze() 能否真正阻止对象被篡改

Object.freeze() 是 JavaScript 中最直接的防篡改手段,但它只做浅冻结:顶层属性不可增删、不可重配置、不可重新赋值,但嵌套对象仍可修改。比如 obj.user.name = 'bob'objfreeze 后依然生效——只要 obj.user 本身没被冻结。

深层冻结需要递归调用 Object.freeze()

没有内置的深冻结 API,必须手动递归处理。常见错误是忽略 null、原始值、函数、Symbol 键或循环引用。

  • 只对 typeof value === 'object'value !== null 的值递归
  • 跳过函数(typeof value === 'function'),因为冻结函数无意义且可能报错
  • WeakMap 记录已处理对象,避免无限递归
  • Object.getOwnPropertyNames() + Object.getOwnPropertySymbols() 才能覆盖所有键
function deepFreeze(obj) {
  if (obj === null || typeof obj !== 'object') return obj;
  if (obj instanceof Date || obj instanceof RegExp) return obj;
  if (typeof obj === 'function') return obj;

  const seen = new WeakMap();
  function _freeze(o) {
    if (o === null || typeof o !== 'object') return o;
    if (seen.has(o)) return o;
    seen.set(o, true);

    Object.getOwnPropertyNames(o).forEach(prop => {
      _freeze(o[prop]);
    });
    Object.getOwnPropertySymbols(o).forEach(sym => {
      _freeze(o[sym]);
    });
    return Object.freeze(o);
  }
  return _freeze(obj);
}

Object.seal() 和 Object.preventExtensions() 的区别在哪

三者层级不同:preventExtensions() 最轻(仅禁止新增属性),seal() 中等(禁止新增 + 禁止删除/重配置已有属性),freeze() 最强(在 seal 基础上还禁止修改属性值)。但三者都只作用于自身,不递归。

  • Object.preventExtensions(obj):还能改值、删属性
  • Object.seal(obj):不能删、不能改 configurable,但能改值(如果 writable: true
  • Object.freeze(obj):默认把所有自有属性设为 writable: false,所以值也不能改

生产环境慎用 freeze 的真实代价

冻结操作本身开销不大,但副作用明显:V8 引擎会将冻结对象标记为“不可变”,后续对其属性访问可能绕过某些优化路径;更关键的是,冻结后无法再用 Object.assign()、解构赋值或任何方式更新字段,调试时 console.log 查看可能显示 [object Object] 而非可展开结构,且 Chrome DevTools 里属性名会变灰、带锁图标,容易误判为“数据没加载出来”。

真正需要冻结的场景其实很窄:配置常量、枚举定义、导出的不可变 schema 描述。日常状态对象用 const 声明 + 不主动重赋值,比盲目 freeze 更实际。


# javascript  # java  # 区别 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Java解压缩zip - 解压缩多个文件或文件夹实例  Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权  电视网站制作tvbox接口,云海电视怎样自定义添加电视源?  Python企业级消息系统教程_KafkaRabbitMQ高并发应用  Laravel怎么设置路由分组Prefix_Laravel多级路由嵌套与命名空间隔离【步骤】  Linux安全能力提升路径_长期防护思维说明【指导】  如何生成腾讯云建站专用兑换码?  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  南京网站制作费用,南京远驱官方网站?  Python正则表达式进阶教程_复杂匹配与分组替换解析  深入理解Android中的xmlns:tools属性  Laravel Blade模板引擎语法_Laravel Blade布局继承用法  Laravel如何为API编写文档_Laravel API文档生成与维护方法  如何快速打造个性化非模板自助建站?  Laravel如何保护应用免受CSRF攻击?(原理和示例)  Win11摄像头无法使用怎么办_Win11相机隐私权限开启教程【详解】  绝密ChatGPT指令:手把手教你生成HR无法拒绝的求职信  Laravel如何处理异常和错误?(Handler示例)  Laravel如何处理CORS跨域问题_Laravel项目CORS配置与解决方案  如何使用 jQuery 正确渲染 Instagram 风格的标签列表  网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?  如何在VPS电脑上快速搭建网站?  laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法  Laravel怎么多语言本地化设置_Laravel语言包翻译与Locale动态切换【手册】  html文件怎么打开证书错误_https协议的html打开提示不安全【指南】  独立制作一个网站多少钱,建立网站需要花多少钱?  php中::能调用final静态方法吗_final修饰静态方法调用规则【解答】  网站视频制作书签怎么做,ie浏览器怎么将网站固定在书签工具栏?  java获取注册ip实例  HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】  香港服务器网站生成指南:免费资源整合与高速稳定配置方案  Python数据仓库与ETL构建实战_Airflow调度流程详解  如何挑选最适合建站的高性能VPS主机?  米侠浏览器网页背景异常怎么办 米侠显示修复  WordPress 子目录安装中正确处理脚本路径的完整指南  如何基于PHP生成高效IDC网络公司建站源码?  Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】  如何快速搭建安全的FTP站点?  Laravel怎么处理异常_Laravel自定义异常处理与错误页面教程  JS实现鼠标移上去显示图片或微信二维码  如何用美橙互联一键搭建多站合一网站?  如何为不同团队 ID 动态生成多个非值班状态按钮  JS中页面与页面之间超链接跳转中文乱码问题的解决办法  Laravel如何部署到服务器_线上部署Laravel项目的完整流程与步骤  制作企业网站建设方案,怎样建设一个公司网站?  详解jQuery停止动画——stop()方法的使用  制作电商网页,电商供应链怎么做?  成都品牌网站制作公司,成都营业执照年报网上怎么办理?  Laravel如何处理CORS跨域请求?(配置示例)  bing浏览器学术搜索入口_bing学术文献检索地址