Package Exports
- @a11d/equals
- @a11d/equals/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@a11d/equals) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@a11d/equals
Value equality for JavaScript. Compares objects, arrays, maps, sets, and functions by structure instead of reference.
import '@a11d/equals'
import { equals } from '@a11d/equals'
const obj1 = { a: 1, b: [1, 2, 3] }
const obj2 = { a: 1, b: [1, 2, 3] }
Object[equals](obj1, obj2) // true
obj1 === obj2 // falseInstallation
npm install @a11d/equalsUsage
Two APIs available:
Symbol-based (recommended):
import { equals } from '@a11d/equals'
obj[equals](other)Global methods (for .equals() syntax or when the symbol conflicts with other libraries):
import '@a11d/equals/global'
obj.equals(other)Built-in types
Objects — Deep comparison of properties. Requires same constructor and all property values to be equal.
Objects with valueOf()
Compared by their primitive values:
const a = { valueOf: () => 1 }
const b = { valueOf: () => 1 }
Object[equals](a, b) // trueundefined vs absence
Missing properties and undefined values are treated as equal, but null is different:
const obj1 = { a: 1, b: undefined }
const obj2 = { a: 1 }
const obj3 = { a: 1, b: null }
Object[equals](obj1, obj2) // true
Object[equals](obj1, obj3) // falsePrototype-less objects
Objects created with Object.create(null) work fine:
const a = Object.create(null)
a.prop = 'value'
const b = { prop: 'value' }
Object[equals](a, b) // trueArrays — Element-by-element comparison.
Nested structures are compared deeply:
const arr1 = [1, 2, { key: 'value' }]
const arr2 = [1, 2, { key: 'value' }]
Object[equals](arr1, arr2) // trueMaps & Sets — Entry/element comparison with deep equality.
Values and elements are compared deeply. Note that Map keys are compared by identity:
const map1 = new Map([['a', { id: 1 }], ['b', { id: 2 }]])
const map2 = new Map([['a', { id: 1 }], ['b', { id: 2 }]])
const set1 = new Set([1, { key: 'value' }])
const set2 = new Set([1, { key: 'value' }])
Object[equals](map1, map2) // true
Object[equals](set1, set2) // trueFunctions — Functions with identical string representation are equal.
const fn1 = () => 42
const fn2 = () => 42
Object[equals](fn1, fn2) // trueNote: This compares the .toString() output, so functions with the same code but different names or closures may differ.
Custom equality
Implement the equals symbol (or .equals() method with global API):
import { equals } from '@a11d/equals'
class Person {
constructor(public name: string, public age: number) {}
[equals](other: unknown): boolean {
return other instanceof Person
&& this.name === other.name
&& this.age === other.age
}
}Lit integration
Use hasChanged to trigger re-renders only on structural changes:
import { hasChanged } from '@a11d/equals'
class MyComponent extends Component {
@property({ type: Object, hasChanged })
data = { name: 'John', items: [1, 2, 3] }
}Without this, Lit re-renders whenever you assign a new object reference, even if the content is identical.