UNPKG

@thi.ng/equiv

Version:

Extensible deep value equivalence checking for any data types

73 lines (72 loc) 1.86 kB
const OBJP = Object.getPrototypeOf({}); const FN = "function"; const STR = "string"; const equiv = (a, b) => { let proto; if (a === b) { return true; } if (a != null) { if (typeof a.equiv === FN) { return a.equiv(b); } } else { return a == b; } if (b != null) { if (typeof b.equiv === FN) { return b.equiv(a); } } else { return a == b; } if (typeof a === STR || typeof b === STR) { return false; } if ((proto = Object.getPrototypeOf(a), proto == null || proto === OBJP) && (proto = Object.getPrototypeOf(b), proto == null || proto === OBJP)) { return equivObject(a, b); } if (typeof a !== FN && a.length !== void 0 && typeof b !== FN && b.length !== void 0) { return equivArrayLike(a, b); } if (a instanceof Set && b instanceof Set) { return equivSet(a, b); } if (a instanceof Map && b instanceof Map) { return equivMap(a, b); } if (a instanceof Date && b instanceof Date) { return a.getTime() === b.getTime(); } if (a instanceof RegExp && b instanceof RegExp) { return a.toString() === b.toString(); } return a !== a && b !== b; }; const equivArrayLike = (a, b, _equiv = equiv) => { let l = a.length; if (l === b.length) { while (l-- > 0 && _equiv(a[l], b[l])) ; } return l < 0; }; const equivSet = (a, b, _equiv = equiv) => a.size === b.size && _equiv([...a.keys()].sort(), [...b.keys()].sort()); const equivMap = (a, b, _equiv = equiv) => a.size === b.size && _equiv([...a].sort(), [...b].sort()); const equivObject = (a, b, _equiv = equiv) => { if (Object.keys(a).length !== Object.keys(b).length) { return false; } for (const k in a) { if (!b.hasOwnProperty(k) || !_equiv(a[k], b[k])) { return false; } } return true; }; export { equiv, equivArrayLike, equivMap, equivObject, equivSet };