UNPKG

@qntm-code/utils

Version:

A collection of useful utility functions with associated TypeScript types. All functions have been unit tested.

106 lines (105 loc) 3.4 kB
/* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-call */ import { isMoment } from './isMoment.js'; /** * Performs a deep comparison between two values to determine if they are equivalent. * * **Note:** This method supports comparing nulls, undefineds, booleans, numbers, strings, Dates, objects, Functions, Arrays, RegExs, Maps, Sets, and Typed Arrays. * * Object objects are compared by their own, not inherited, enumerable properties. * * Functions and DOM nodes are compared by strict equality, i.e. ===. * * The order of the array items must be the same for the arrays to be equal. */ export function isEqual(a, b) { if (a === b) { return true; } if (a && b && typeof a === 'object' && typeof b === 'object') { if (a.constructor !== b.constructor) { return false; } if (Array.isArray(a)) { const aLength = a.length; if (aLength !== b.length) { return false; } for (let i = 0; i < aLength; i++) { if (!isEqual(a[i], b[i])) { return false; } } return true; } if (a instanceof Map && b instanceof Map) { if (a.size !== b.size) { return false; } for (const i of a.entries()) { if (!b.has(i[0])) { return false; } } for (const i of a.entries()) { if (!isEqual(i[1], b.get(i[0]))) { return false; } } return true; } if (a instanceof Set && b instanceof Set) { if (a.size !== b.size) { return false; } for (const i of a.entries()) { if (!b.has(i[0])) { return false; } } return true; } if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const length = a.length; if (length !== b.length) { return false; } for (let i = 0; i < length; i++) { if (a[i] !== b[i]) { return false; } } return true; } if (a.constructor === RegExp) { return a.source === b.source && a.flags === b.flags; } if (a.valueOf !== Object.prototype.valueOf) { return a.valueOf() === b.valueOf(); } if (a.toString !== Object.prototype.toString) { return a.toString() === b.toString(); } if (isMoment(a)) { if (!isMoment(b)) { return false; } return a.isSame(b); } const keysA = Object.keys(a); const keysB = Object.keys(b); const keysALength = keysA.length; if (keysALength !== keysB.length) { return false; } for (let i = 0; i < keysALength; i++) { const key = keysA[i]; if (!isEqual(a[key], b[key])) { return false; } } return true; } return a !== a && b !== b; }