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提供的深度比較方法
實際應用場景
- 狀態管理: 比較應用狀態變化
- 表單驗證: 檢測表單數據是否改變
- 緩存管理: 比較緩存鍵
- 配置管理: 檢測配置變化
- 測試: 深度比較測試結果