Skip to content

deepEqual 深度相等比较

用于深度比较两个值是否相等。支持:原始类型(含 NaN)、数组、普通对象、DateRegExpMapSetArrayBufferDataViewTypedArrayError 等;并处理循环引用。

安装与引入

按需导入(推荐)

ts
import { deepEqual } from '@cuixingjian/cui-utils'

子路径导入

ts
import { deepEqual } from '@cuixingjian/cui-utils/deepEqual'

使用示例

基础类型比较

ts
import { deepEqual } from '@cuixingjian/cui-utils/deepEqual'

// 原始类型
deepEqual(1, 1) // true
deepEqual(NaN, NaN) // true
deepEqual(0, -0) // true(本实现认为 +0 与 -0 相等)

// 对象与数组
deepEqual({ a: 1, b: [1, 2] }, { a: 1, b: [1, 2] }) // true
deepEqual([{ x: 1 }], [{ x: 1 }]) // true

// Date / RegExp
deepEqual(new Date('2020-01-01'), new Date('2020-01-01')) // true
deepEqual(/abc/gi, /abc/gi) // true

// Map / Set(无序比较)
const m1 = new Map([[{ k: 1 }, { v: 1 }], ['x', 2]])
const m2 = new Map([['x', 2], [{ k: 1 }, { v: 1 }]])
deepEqual(m1, m2) // true

const s1 = new Set([{ a: 1 }, 2])
const s2 = new Set([2, { a: 1 }])
deepEqual(s1, s2) // true

// TypedArray / ArrayBuffer / DataView
deepEqual(new Uint8Array([1, 2]), new Uint8Array([1, 2])) // true

// 循环引用
const a: any = { self: null }
const b: any = { self: null }
a.self = a; b.self = b
deepEqual(a, b) // true

API 说明

函数签名

ts
function deepEqual(a: any, b: any): boolean

参数

参数名类型说明
aany第一个比较值
bany第二个比较值

返回值

返回 boolean,表示两个值是否深度相等。


注意事项

相等规则

  • 原始类型:使用 === 比较,但 NaNNaN 视为相等
  • +0 与 -0:默认视为相等
  • 引用类型:递归比较内部结构

特殊类型处理

  • Date:比较时间戳
  • RegExp:比较 source 和 flags
  • Map/Set:不依赖元素顺序,会匹配对应项(大集合时性能开销较大)
  • ArrayBuffer/DataView/TypedArray:按字节或元素逐一比较
  • Error:比较 name 和 message
  • 函数/Promise/Symbol/WeakMap/WeakSet:按引用相等比较

循环引用

使用 WeakMap 跟踪已比较的对象,避免无限递归。

典型场景

  • 单元测试:验证复杂对象是否相等
  • 状态比较:检测状态是否发生变化
  • 表单验证:比较表单数据与初始值
  • 缓存判断:判断数据是否需要更新

源码

展开查看
ts
// 源码来自 @cuixingjian/cui-utils/deepEqual
export function deepEqual(a: any, b: any): boolean {
  if (a === b) {
    return a !== 0 || 1 / a === 1 / b
  }
  if (Number.isNaN(a) && Number.isNaN(b)) return true
  const typeA = typeof a
  const typeB = typeof b
  if (typeA !== 'object' || a === null) return false
  if (typeB !== 'object' || b === null) return false
  const seenA = new WeakMap<object, object>()
  const seenB = new WeakMap<object, object>()
  return equalObject(a, b, seenA, seenB)
}
// ...(其余实现见源码文件)