isEqual
深度比较两个值是否相等,支持对象、数组、基本类型等。
基础用法
typescript
import { isEqual } from 'radash'
console.log(isEqual(1, 1)) // true
console.log(isEqual('hello', 'hello')) // true
console.log(isEqual([1, 2, 3], [1, 2, 3])) // true
console.log(isEqual({ a: 1 }, { a: 1 })) // true
console.log(isEqual(1, '1')) // false
语法
typescript
function isEqual(a: any, b: any): boolean
参数
a
(any): 第一个要比较的值b
(any): 第二个要比较的值
返回值
返回一个布尔值,表示两个值是否深度相等。
示例
基本类型比较
typescript
import { isEqual } from 'radash'
// 数字
console.log(isEqual(1, 1)) // true
console.log(isEqual(1, 2)) // false
console.log(isEqual(1, '1')) // false
console.log(isEqual(0, -0)) // true
console.log(isEqual(NaN, NaN)) // true
// 字符串
console.log(isEqual('hello', 'hello')) // true
console.log(isEqual('hello', 'world')) // false
console.log(isEqual('', '')) // true
// 布尔值
console.log(isEqual(true, true)) // true
console.log(isEqual(false, false)) // true
console.log(isEqual(true, false)) // false
// null 和 undefined
console.log(isEqual(null, null)) // true
console.log(isEqual(undefined, undefined)) // true
console.log(isEqual(null, undefined)) // false
数组比较
typescript
import { isEqual } from 'radash'
// 简单数组
console.log(isEqual([1, 2, 3], [1, 2, 3])) // true
console.log(isEqual([1, 2, 3], [1, 2])) // false
console.log(isEqual([1, 2, 3], [1, 3, 2])) // false
// 嵌套数组
console.log(isEqual([[1, 2], [3, 4]], [[1, 2], [3, 4]])) // true
console.log(isEqual([[1, 2], [3, 4]], [[1, 2], [3, 5]])) // false
// 空数组
console.log(isEqual([], [])) // true
console.log(isEqual([1], [])) // false
// 混合类型数组
console.log(isEqual([1, 'hello', true], [1, 'hello', true])) // true
console.log(isEqual([1, 'hello', true], [1, 'hello', false])) // false
对象比较
typescript
import { isEqual } from 'radash'
// 简单对象
console.log(isEqual({ a: 1, b: 2 }, { a: 1, b: 2 })) // true
console.log(isEqual({ a: 1, b: 2 }, { b: 2, a: 1 })) // true (属性顺序不重要)
console.log(isEqual({ a: 1, b: 2 }, { a: 1, b: 3 })) // false
// 嵌套对象
console.log(isEqual(
{ user: { name: 'Alice', age: 25 } },
{ user: { name: 'Alice', age: 25 } }
)) // true
console.log(isEqual(
{ user: { name: 'Alice', age: 25 } },
{ user: { name: 'Bob', age: 25 } }
)) // false
// 空对象
console.log(isEqual({}, {})) // true
console.log(isEqual({ a: 1 }, {})) // false
复杂对象比较
typescript
import { isEqual } from 'radash'
const obj1 = {
id: 1,
name: 'Alice',
profile: {
email: 'alice@example.com',
address: {
city: 'Beijing',
country: 'China'
},
preferences: {
theme: 'dark',
notifications: true
}
},
hobbies: ['reading', 'swimming'],
metadata: {
createdAt: new Date('2023-01-01'),
tags: ['user', 'active']
}
}
const obj2 = {
id: 1,
name: 'Alice',
profile: {
email: 'alice@example.com',
address: {
city: 'Beijing',
country: 'China'
},
preferences: {
theme: 'dark',
notifications: true
}
},
hobbies: ['reading', 'swimming'],
metadata: {
createdAt: new Date('2023-01-01'),
tags: ['user', 'active']
}
}
console.log(isEqual(obj1, obj2)) // true
函数比较
typescript
import { isEqual } from 'radash'
const func1 = (x: number) => x * 2
const func2 = (x: number) => x * 2
const func3 = (x: number) => x + 2
console.log(isEqual(func1, func1)) // true (相同引用)
console.log(isEqual(func1, func2)) // false (不同引用)
console.log(isEqual(func1, func3)) // false
日期比较
typescript
import { isEqual } from 'radash'
const date1 = new Date('2023-01-01T00:00:00Z')
const date2 = new Date('2023-01-01T00:00:00Z')
const date3 = new Date('2023-01-02T00:00:00Z')
console.log(isEqual(date1, date2)) // true
console.log(isEqual(date1, date3)) // false
console.log(isEqual(date1, '2023-01-01')) // false
正则表达式比较
typescript
import { isEqual } from 'radash'
const regex1 = /hello/i
const regex2 = /hello/i
const regex3 = /world/i
console.log(isEqual(regex1, regex1)) // true (相同引用)
console.log(isEqual(regex1, regex2)) // false (不同引用)
console.log(isEqual(regex1, regex3)) // false
特殊值比较
typescript
import { isEqual } from 'radash'
// NaN 比较
console.log(isEqual(NaN, NaN)) // true
console.log(isEqual(NaN, 0)) // false
// Infinity 比较
console.log(isEqual(Infinity, Infinity)) // true
console.log(isEqual(-Infinity, -Infinity)) // true
console.log(isEqual(Infinity, -Infinity)) // false
// 零值比较
console.log(isEqual(0, -0)) // true
console.log(isEqual(0, 0)) // true
循环引用处理
typescript
import { isEqual } from 'radash'
const obj1: any = { a: 1 }
obj1.self = obj1
const obj2: any = { a: 1 }
obj2.self = obj2
// 注意:循环引用可能导致无限递归
// 在实际使用中需要小心处理
console.log(isEqual(obj1, obj2)) // 可能为 true 或抛出错误
类型安全比较
typescript
import { isEqual } from 'radash'
// 不同类型的基本值
console.log(isEqual(1, '1')) // false
console.log(isEqual(true, 1)) // false
console.log(isEqual(null, undefined)) // false
console.log(isEqual([], {})) // false
// 相同类型的不同值
console.log(isEqual(1, 2)) // false
console.log(isEqual('hello', 'world')) // false
console.log(isEqual(true, false)) // false
实际应用场景
typescript
import { isEqual } from 'radash'
// 表单数据比较
function hasFormChanged(originalData: any, currentData: any) {
return !isEqual(originalData, currentData)
}
const originalForm = {
name: 'Alice',
email: 'alice@example.com',
preferences: {
theme: 'dark',
notifications: true
}
}
const currentForm = {
name: 'Alice',
email: 'alice@example.com',
preferences: {
theme: 'light', // 改变了
notifications: true
}
}
console.log(hasFormChanged(originalForm, currentForm)) // true
配置比较
typescript
import { isEqual } from 'radash'
function hasConfigChanged(oldConfig: any, newConfig: any) {
return !isEqual(oldConfig, newConfig)
}
const oldConfig = {
server: {
port: 3000,
host: 'localhost'
},
database: {
url: 'postgresql://localhost:5432/mydb',
pool: {
min: 1,
max: 10
}
}
}
const newConfig = {
server: {
port: 3000,
host: 'localhost'
},
database: {
url: 'postgresql://localhost:5432/mydb',
pool: {
min: 2, // 改变了
max: 10
}
}
}
console.log(hasConfigChanged(oldConfig, newConfig)) // true
状态比较
typescript
import { isEqual } from 'radash'
function hasStateChanged(oldState: any, newState: any) {
return !isEqual(oldState, newState)
}
const oldState = {
user: {
id: 1,
name: 'Alice',
isLoggedIn: true
},
settings: {
theme: 'dark',
language: 'en'
}
}
const newState = {
user: {
id: 1,
name: 'Alice',
isLoggedIn: true
},
settings: {
theme: 'light', // 改变了
language: 'en'
}
}
console.log(hasStateChanged(oldState, newState)) // true
缓存键比较
typescript
import { isEqual } from 'radash'
class Cache {
private cache = new Map()
get(key: any) {
for (const [cachedKey, value] of this.cache) {
if (isEqual(cachedKey, key)) {
return value
}
}
return undefined
}
set(key: any, value: any) {
this.cache.set(key, value)
}
}
const cache = new Cache()
const params1 = { userId: 1, filter: 'active' }
const params2 = { userId: 1, filter: 'active' }
cache.set(params1, 'cached data')
console.log(cache.get(params2)) // 'cached data' (因为 isEqual(params1, params2) 为 true)
注意事项
- 深度比较: 递归比较所有嵌套属性
- 类型严格: 不同类型的基本值不相等
- 引用比较: 函数和正则表达式按引用比较
- 循环引用: 可能导致无限递归
- 性能: 对于大型对象,比较可能较慢
与其他方法的区别
===
: 严格相等,不进行深度比较==
: 宽松相等,会进行类型转换isEqual()
: radash提供的深度比较方法
实际应用场景
- 状态管理: 比较应用状态变化
- 表单验证: 检测表单数据是否改变
- 缓存管理: 比较缓存键
- 配置管理: 检测配置变化
- 测试: 深度比较测试结果