深层比较需递归检查类型、值和嵌套结构,处理NaN、数组、循环引用等边界;===仅比引用,JSON.stringify会丢失undefined/函数/Symbol且受属性顺序影响;生产推荐lodash.isEqual。

不能用 ===,也不能靠 JSON.stringify() 草率对比。真正判断两个对象内容是否完全相同,必须做深层比较——逐层递归检查类型、值、嵌套结构,并处理各种边界情况。
为什么 === 和 JSON.stringify 都不行
— === 只比内存地址,两个一模一样的对象也返回 false
— JSON.stringify(a) === JSON.stringify(b) 会丢数据:undefined、函数、Symbol 被忽略;NaN 变成 null;属性顺序不同就判为不等;遇到循环引用直接报错
自己写简易 deepEqual 要注意这些点
基础逻辑是递归 + 类型分治,关键细节包括:
— 先快速拦截:同一引用、null、非对象类型直接用 ===
— 特别处理 NaN:它不等于自身,需用 Number.isNaN() 单独判断
— 用 Object.keys() 或 Object.getOwnPropertyNames() 获取自有属性,避免原型链干扰
— 数组要单独识别(Array.isArray()),再按索引逐项比,不能当普通对象处理
— 对象属性数量不同、某 key 在一个对象里存在另一个不存在,直接返回 false
生产环境推荐用成熟工具库
自己实现容易漏掉循环引用、Date、RegExp、Map/Set 等复杂类型。
— lodash.isEqual(a, b) 是最常用选择,覆盖全面,性能优化好,支持循环引用
— 如果项目已用 underscore,可用 _.isEqual
— React 生态中,fast-deep-equal 更轻量,适合只比 plain object 和 array 的场景
什么情况下可以不用深层比较
深层比较开销大,尤其对象深或体积大时:
— React 中做 shouldComponentUpdate 或 useMemo 依赖项,优先用浅比较(Object.is)+ 不可变更新
— 后端返回数据带唯一 id,前端用 id 判定是否为同一实体,比内容更高效可靠
— 表单校验或配置比对等低频操作,若对象结构固定且简单,可定制一层浅比 + 关键字段白名单


















