深入探索JavaScript:精准判断对象间的“真”相等【含代码示例】

深入探索JavaScript:精准判断对象间的“真”相等【含代码示例】

    • 基本概念与作用说明
      • == 与 === 的区别
      • Object.is()
      • 深度比较的必要性
    • 实战案例:五种深度比较策略
      • 案例一:朴素递归法
      • 案例二:JSON.stringify()法(谨慎使用)
      • 案例三:lodash _.isEqual()
      • 案例四:Reflect.ownKeys()与Proxy的高级组合
      • 案例五:使用WeakMap避免循环引用
    • 不同角度的功能使用思路
    • 实际开发技巧与问题排查
    • 防范漏洞
    • 结论与讨论

在JavaScript的世界里,对象比较从来不是一件直截了当的事情。本文将带你深入探讨如何在JS中准确判断两个对象是否相等,不仅涵盖基础概念,还会通过实战案例、技巧分享及问题排查,让你彻底掌握这一核心技能。无论你是前端领域的初学者,还是有一定经验的开发者,都能在这里找到宝贵的知识点和实战策略。

基本概念与作用说明

== 与 === 的区别

首先,理解==(宽松相等)和===(严格相等)的区别至关重要。===要求两边的值和类型完全相同才认为相等,而==则会在比较前进行类型转换,可能导致意外结果。对于对象来说,无论是==还是===,都只会比较它们的引用是否相同,而非内容是否一致。

Object.is()

虽然不常用,但Object.is()方法提供了一种更精确的比较方式,它在处理NaN+0/-0时表现得更加合理,但对于对象依然只比较引用。

深度比较的必要性

对象的比较往往需要“深度比较”,即比较两个对象的所有属性及嵌套对象的值是否一一对应相等,这在处理复杂数据结构时尤为重要。

实战案例:五种深度比较策略

案例一:朴素递归法

function isEqual(obj1, obj2) {// 基础类型直接比较if (obj1 === obj2 || (Number.isNaN(obj1) && Number.isNaN(obj2))) return true;// 类型或长度不同则不相等if (typeof obj1 !== typeof obj2 || Array.isArray(obj1) !== Array.isArray(obj2)) return false;// 对象或数组进行递归比较const keys1 = Object.keys(obj1);const keys2 = Object.keys(obj2);if (keys1.length !== keys2.length) return false;for (const key of keys1) {if (!isEqual(obj1[key], obj2[key])) return false;}return true;
}

案例二:JSON.stringify()法(谨慎使用)

function simpleCompare(obj1, obj2) {return JSON.stringify(obj1) === JSON.stringify(obj2);
}
// 注意:此方法不适用于循环引用的对象,且会丢失函数、undefined等信息。

案例三:lodash _.isEqual()

引入第三方库lodash,其_.isEqual()方法提供了全面且高效的深度比较。

import _ from 'lodash';
console.log(_.isEqual(object1, object2));

案例四:Reflect.ownKeys()与Proxy的高级组合

适用于需要更精细控制比较逻辑的场景,比如忽略某些属性或自定义比较规则。

function deepEqualAdvanced(obj1, obj2, options = {}) {const { ignoreKeys = [], customComparers = {} } = options;if (obj1 === obj2) return true;const keys1 = Reflect.ownKeys(obj1);const keys2 = Reflect.ownKeys(obj2);if (keys1.length !== keys2.length) return false;for (const key of keys1) {if (ignoreKeys.includes(key)) continue;const comparer = customComparers[key] || isEqual;if (!comparer(obj1[key], obj2[key])) return false;}return true;
}

案例五:使用WeakMap避免循环引用

针对含有循环引用的对象,可以利用WeakMap来跟踪已访问过的对象,避免无限循环。

function deepEqualWithCycles(obj1, obj2, visited = new WeakMap()) {if (obj1 === obj2) return true;if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) {return false;}if (visited.has(obj1) && visited.get(obj1) === obj2) return true;visited.set(obj1, obj2);const keys1 = Object.keys(obj1);const keys2 = Object.keys(obj2);if (keys1.length !== keys2.length) return false;for (const key of keys1) {if (!deepEqualWithCycles(obj1[key], obj2[key], visited)) return false;}return true;
}

不同角度的功能使用思路

  • 性能优化:在处理大量数据比较时,考虑提前终止比较或使用更高效的数据结构。
  • 安全性:避免直接使用不可信的输入进行深度比较,防止潜在的安全风险,如DoS攻击。

实际开发技巧与问题排查

  • 调试技巧:利用console.log或调试器逐步检查比较过程,特别是处理复杂对象结构时。
  • 问题排查:遇到比较失败,检查是否有未定义属性、特殊类型的值(如函数、Symbol)或循环引用。
  • 性能考量:在性能敏感的应用中,评估并选择最合适的比较方法,必要时实现定制化逻辑。

防范漏洞

  • 避免使用eval:在解析字符串为对象进行比较时,绝对不要使用eval,以防注入攻击。
  • 数据验证:比较前先验证输入数据,确保其格式安全可靠,避免执行恶意代码。

结论与讨论

通过上述探讨,我们深入学习了在JavaScript中如何有效地判断两个对象是否相等,从基础概念到高级技巧,从常见方法到安全实践,每一步都是前端开发者不可或缺的技能。但技术探索永无止境,你是否遇到过特别棘手的对象比较问题?或者有更高效的方法想要分享?欢迎在评论区留下你的见解和经验,让我们一起提升前端开发的艺术。


欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。


推荐:DTcode7的博客首页。
一个做过前端开发的产品经理,经历过睿智产品的折磨导致脱发之后,励志要翻身农奴把歌唱,一边打入敌人内部一边持续提升自己,为我们广大开发同胞谋福祉,坚决抵制睿智产品折磨我们码农兄弟!


专栏系列(点击解锁)学习路线(点击解锁)知识定位
《微信小程序相关博客》持续更新中~结合微信官方原生框架、uniapp等小程序框架,记录请求、封装、tabbar、UI组件的学习记录和使用技巧等
《AIGC相关博客》持续更新中~AIGC、AI生产力工具的介绍,例如stable diffusion这种的AI绘画工具安装、使用、技巧等总结
《HTML网站开发相关》《前端基础入门三大核心之html相关博客》前端基础入门三大核心之html板块的内容,入坑前端或者辅助学习的必看知识
《前端基础入门三大核心之JS相关博客》前端JS是JavaScript语言在网页开发中的应用,负责实现交互效果和动态内容。它与HTML和CSS并称前端三剑客,共同构建用户界面。
通过操作DOM元素、响应事件、发起网络请求等,JS使页面能够响应用户行为,实现数据动态展示和页面流畅跳转,是现代Web开发的核心
《前端基础入门三大核心之CSS相关博客》介绍前端开发中遇到的CSS疑问和各种奇妙的CSS语法,同时收集精美的CSS效果代码,用来丰富你的web网页
《canvas绘图相关博客》Canvas是HTML5中用于绘制图形的元素,通过JavaScript及其提供的绘图API,开发者可以在网页上绘制出各种复杂的图形、动画和图像效果。Canvas提供了高度的灵活性和控制力,使得前端绘图技术更加丰富和多样化
《Vue实战相关博客》持续更新中~详细总结了常用UI库elementUI的使用技巧以及Vue的学习之旅
《python相关博客》持续更新中~Python,简洁易学的编程语言,强大到足以应对各种应用场景,是编程新手的理想选择,也是专业人士的得力工具
《sql数据库相关博客》持续更新中~SQL数据库:高效管理数据的利器,学会SQL,轻松驾驭结构化数据,解锁数据分析与挖掘的无限可能
《算法系列相关博客》持续更新中~算法与数据结构学习总结,通过JS来编写处理复杂有趣的算法问题,提升你的技术思维
《IT信息技术相关博客》持续更新中~作为信息化人员所需要掌握的底层技术,涉及软件开发、网络建设、系统维护等领域的知识
《信息化人员基础技能知识相关博客》无论你是开发、产品、实施、经理,只要是从事信息化相关行业的人员,都应该掌握这些信息化的基础知识,可以不精通但是一定要了解,避免日常工作中贻笑大方
《信息化技能面试宝典相关博客》涉及信息化相关工作基础知识和面试技巧,提升自我能力与面试通过率,扩展知识面
《前端开发习惯与小技巧相关博客》持续更新中~罗列常用的开发工具使用技巧,如 Vscode快捷键操作、Git、CMD、游览器控制台等
《photoshop相关博客》持续更新中~基础的PS学习记录,含括PPI与DPI、物理像素dp、逻辑像素dip、矢量图和位图以及帧动画等的学习总结
日常开发&办公&生产【实用工具】分享相关博客》持续更新中~分享介绍各种开发中、工作中、个人生产以及学习上的工具,丰富阅历,给大家提供处理事情的更多角度,学习了解更多的便利工具,如Fiddler抓包、办公快捷键、虚拟机VMware等工具

吾辈才疏学浅,摹写之作,恐有瑕疵。望诸君海涵赐教。望轻喷,嘤嘤嘤
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。愿斯文对汝有所裨益,纵其简陋未及渊博,亦足以略尽绵薄之力。倘若尚存阙漏,敬请不吝斧正,俾便精进!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/19101.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

postman教程-6-发送delete请求

领取资料,咨询答疑,请➕wei: June__Go 上一小节我们学习了postman发送put请求的方法,本小节我们讲解一下postman发送delete请求的方法。 HTTP DELETE 请求是一种用于删除指定资源的请求方法。在RESTful API 设计中,DELETE 请求…

tensorboard可视化时save_graph报错ERROR: Graphs differed across invocations!的一个解决方法

在使用tensorboard可视化,经常会将模型通过save_graph方法保存下来,方便查看结构。在使用save_graph经常会遇到错误(至少我经常遇到),对于我,最常见的一个错误为 Tracing failed sanity checks! ERROR: Gr…

GPT-4o:重塑人机交互的未来

一个愿意伫立在巨人肩膀上的农民...... 一、推出 在人工智能(AI)领域,自然语言处理(NLP)技术一直被视为连接人类与机器的桥梁。近年来,随着深度学习技术的快速发展,NLP领域迎来了前所未有的变革…

ARM-V9 RME(Realm Management Extension)系统架构之系统能力的执行隔离

安全之安全(security)博客目录导读 目录 一、执行隔离 1、安全状态 2、安全模型 本博客探讨 RME 所需的系统能力,以保证 Arm CCA 对于 Realms 的安全性和隔离特性。 一、执行隔离 1、安全状态 RME 系统支持以下安全状态: 非安全 (Non-secure)安全…

Orange Pi Kunpeng Pro测评

#创作灵感# 参加树莓派鲲鹏开发版的测评活动,也想体验一下该开发版,之前有做过树莓派和香橙派的开发,刚好借此机会了解一下鲲鹏,所以就有了这篇测评文章。 #正文# 引言 说是测评,其实也没有多少测评方面的内容&…

前端面试题23-34

23. 说说你对 Promise 的理解 Promise 是 ECMAScript6 引入的一种异步编程解决方案,用于处理异步操作。它表示一个尚未完成但最终会结束的操作,具有三种状态:pending(进行中)、fulfilled(已完成&#xff0…

代码随想录算法训练营Day22|235.二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

二叉搜索树的最近公共祖先 不考虑二叉搜索树这一条件的话,普通的二叉搜索树搜索最近的公共祖先就是昨日的做法,这种做法也能解决二叉搜索树的最近公共祖先。 class Solution { public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, Tr…

贪心算法02(leetcode122/55/4)

参考资料: https://programmercarl.com/0122.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%97%B6%E6%9C%BAII.html 122. 买卖股票的最佳时机 II 题目描述: 给你一个整数数组 prices ,其中 prices[i] 表示某支股票第…

STM32读写内部FLASH读取芯片id

文章目录 读写内部Flash接线程序编写测试效果补充 读取芯片id代码编写 读写内部Flash 接线 程序编写 首先使用ThisFlash.c来写入flash的基本操作,写入、读取、擦除,然后使用Store.c配合数组来进行主存与flash的交互 ThisFlash.c #include "stm32…

为什么工控现场会用到Profinet转Modbus网关设备

一、背景: 工控现场之所以需要使用Profinet转Modbus网关,是因为工控系统中常常存在不同厂家设备之间通讯协议不一致的问题。而Modbus和Profinet分别代表着两种不同的通信协议,Profinet通常用于较新的设备,而Modbus则是比较老的通…

思科防火墙ASA Version 9.1(1) 怎么配置静态NAT,把内网ip192.168.1.10 端口1000映射到公网端口1000上?

环境: 思科防火墙5520 ASA Version 9.1(1) 问题描述: 思科防火墙ASA Version 9.1(1) 怎么配置静态NAT,把内网ip192.168.1.10 端口1000映射到公网端口1000上? 解决方案: 旧版本8.0 1.做之前要先查一下有没有端口被占用,要和业务确认2.sh Xlate | in 10011 端口 这条…

ch2应用层--计算机网络期末复习

2.1应用层协议原理 网络应用程序位于应用层 开发网络应用程序: 写出能够在不同的端系统上通过网络彼此通信的程序 2.1.1网络应用程序体系结构分类: 客户机/服务器结构 服务器: 总是打开(always-on)具有固定的、众所周知的IP地址 主机群集常被用于创建强大的虚拟服务器 客…

MongoDB CRUD操作:快照查询

MongoDB CRUD操作:快照查询 文章目录 MongoDB CRUD操作:快照查询对比本地和快照的读关注举例从相同的时间点运行查询从过去某个时刻读取数据的一致状态 配置快照保留时间磁盘空间和历史记录 使用快照查询可以读取最近某个时间点的数据,而且从…

基于51单片机的温控风扇的设计–仿真设计

可实现通过DS18B20测量当前环境温度 可实现通过温度自动控制风扇转速 可实现通过按键设置不同风速对应的温度 可实现通过按键切换自动、手动模式 可实现在手动模式下通过按键调整风扇转速 可实现通过LCD1602显示温度、风扇转速挡位、自动/手动模式

【C++】模拟实现string类

🦄个人主页:修修修也 🎏所属专栏:C ⚙️操作环境:Visual Studio 2022 目录 一.了解项目功能 二.逐步实现项目功能模块及其逻辑详解 🎏构建成员变量 🎏实现string类默认成员函数 📌构造函数 📌析构函数…

k8s 全面掌控日志系统

概述 为了提高系统运维和故障排查的效率, 日志系统采用 ELK(Elasticsearch、Logstash、Kibana)技术栈,通过 FileBeats 作为日志收集器,将来自不同节点的日志数据汇总并存储在 Elasticsearch 中,最终通过 K…

创建一个新的Spring Security应用程序,并使用JDBC连接数据库

创建一个新的Spring Security应用程序,并使用JDBC连接数据库 在这个教程中,我们将学习如何创建一个新的Spring Security应用程序,使用JDBC连接数据库以获取用户信息并进行认证。我们还将学习如何配置Spring Security以从数据库中获取用户和权…

Vue3使用Composition API实现响应式

title: Vue3使用Composition API实现响应式 date: 2024/5/29 下午8:10:24 updated: 2024/5/29 下午8:10:24 categories: 前端开发 tags: Vue3CompositionRefsReactiveWatchLifecycleDebugging 1. 介绍 Composition API是Vue.js 3中新增的一组API,用于在组件中组…

SQL 语言:嵌入式 SQL 和动态 SQL

文章目录 基本概述嵌入式 SQL动态 SQL总结 基本概述 嵌入式SQL和动态SQL是两种在应用程序中嵌入和使用SQL语句的方法。它们都允许开发人员在编程语言中编写SQL语句,以便在应用程序中执行数据库操作。然而,这两种方法在实现方式、性能和灵活性方面存在一…

Java数据结构与算法(红黑树)

前言 红黑树是一种自平衡二叉搜索树,确保在插入和删除操作后,树的高度保持平衡,从而保证基本操作(插入、删除、查找)的时间复杂度为O(log n)。 实现原理 红黑树具有以下性质: 每个节点要么是红色&#…