isEqual
Performs deep comparison of two values for equality, supporting objects, arrays, primitive types, etc.
Basic Usage
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
Syntax
typescript
function isEqual(a: any, b: any): boolean
Parameters
a
(any): The first value to compareb
(any): The second value to compare
Return Value
Returns a boolean indicating whether the two values are deeply equal.
Examples
Primitive Type Comparison
typescript
import { isEqual } from 'radash'
// Numbers
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
// Strings
console.log(isEqual('hello', 'hello')) // true
console.log(isEqual('hello', 'world')) // false
console.log(isEqual('', '')) // true
// Booleans
console.log(isEqual(true, true)) // true
console.log(isEqual(false, false)) // true
console.log(isEqual(true, false)) // false
// null and undefined
console.log(isEqual(null, null)) // true
console.log(isEqual(undefined, undefined)) // true
console.log(isEqual(null, undefined)) // false
Array Comparison
typescript
import { isEqual } from 'radash'
// Simple arrays
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
// Nested arrays
console.log(isEqual([[1, 2], [3, 4]], [[1, 2], [3, 4]])) // true
console.log(isEqual([[1, 2], [3, 4]], [[1, 2], [3, 5]])) // false
// Empty arrays
console.log(isEqual([], [])) // true
console.log(isEqual([1], [])) // false
// Mixed type arrays
console.log(isEqual([1, 'hello', true], [1, 'hello', true])) // true
console.log(isEqual([1, 'hello', true], [1, 'hello', false])) // false
Object Comparison
typescript
import { isEqual } from 'radash'
// Simple objects
console.log(isEqual({ a: 1, b: 2 }, { a: 1, b: 2 })) // true
console.log(isEqual({ a: 1, b: 2 }, { b: 2, a: 1 })) // true (property order doesn't matter)
console.log(isEqual({ a: 1, b: 2 }, { a: 1, b: 3 })) // false
// Nested objects
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
// Empty objects
console.log(isEqual({}, {})) // true
console.log(isEqual({ a: 1 }, {})) // false
Complex Object Comparison
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
Function Comparison
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 (same reference)
console.log(isEqual(func1, func2)) // false (different references)
console.log(isEqual(func1, func3)) // false
Date Comparison
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
Regular Expression Comparison
typescript
import { isEqual } from 'radash'
const regex1 = /hello/i
const regex2 = /hello/i
const regex3 = /world/i
console.log(isEqual(regex1, regex1)) // true (same reference)
console.log(isEqual(regex1, regex2)) // false (different references)
console.log(isEqual(regex1, regex3)) // false
Special Value Comparison
typescript
import { isEqual } from 'radash'
// NaN comparison
console.log(isEqual(NaN, NaN)) // true
console.log(isEqual(NaN, 0)) // false
// Infinity comparison
console.log(isEqual(Infinity, Infinity)) // true
console.log(isEqual(-Infinity, -Infinity)) // true
console.log(isEqual(Infinity, -Infinity)) // false
// Zero comparison
console.log(isEqual(0, -0)) // true
console.log(isEqual(0, 0)) // true
Circular Reference Handling
typescript
import { isEqual } from 'radash'
const obj1: any = { a: 1 }
obj1.self = obj1
const obj2: any = { a: 1 }
obj2.self = obj2
// Note: Circular references may cause infinite recursion
// Care should be taken in actual usage
console.log(isEqual(obj1, obj2)) // May be true or throw error
Type-Safe Comparison
typescript
import { isEqual } from 'radash'
// Different types of primitive values
console.log(isEqual(1, '1')) // false
console.log(isEqual(true, 1)) // false
console.log(isEqual(null, undefined)) // false
console.log(isEqual([], {})) // false
// Same type, different values
console.log(isEqual(1, 2)) // false
console.log(isEqual('hello', 'world')) // false
console.log(isEqual(true, false)) // false
Practical Application Scenarios
typescript
import { isEqual } from 'radash'
// Form data comparison
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', // Changed
notifications: true
}
}
console.log(hasFormChanged(originalForm, currentForm)) // true
Configuration Comparison
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, // Changed
max: 10
}
}
}
console.log(hasConfigChanged(oldConfig, newConfig)) // true
State Comparison
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', // Changed
language: 'en'
}
}
console.log(hasStateChanged(oldState, newState)) // true
Cache Key Comparison
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' (because isEqual(params1, params2) is true)
Notes
- Deep Comparison: Recursively compares all nested properties
- Type Strict: Primitive values of different types are not equal
- Reference Comparison: Functions and regular expressions are compared by reference
- Circular References: May cause infinite recursion
- Performance: Comparison may be slow for large objects
Differences from Other Methods
===
: Strict equality, does not perform deep comparison==
: Loose equality, performs type conversionisEqual()
: Deep comparison method provided by radash
Practical Application Scenarios
- State Management: Compare application state changes
- Form Validation: Detect form data changes
- Cache Management: Compare cache keys
- Configuration Management: Detect configuration changes
- Testing: Deep comparison of test results