Skip to content

Instantly share code, notes, and snippets.

@yuri-kiss
Last active June 5, 2025 05:07
Show Gist options
  • Save yuri-kiss/3f631f66ec0220e7359af6729b352442 to your computer and use it in GitHub Desktop.
Save yuri-kiss/3f631f66ec0220e7359af6729b352442 to your computer and use it in GitHub Desktop.
Unfinished object comparison inspired by mist's attempt. https://github.com/Mistium/mist.js/blob/main/mist.js
// latest edit: NaN checking
function ocom(a, b) {
// Fast check.
if (Object.is(a, b) || (a === b) || (Number.isNaN(a) && Number.isNaN(b))) return true;
// The === would have caught it if they were the same.
if (a instanceof Symbol || b instanceof Symbol) return false;
// Custom matcher.
if (a[ocom.matcher] && b[ocom.matcher]) return !!a[ocom.matcher](b);
// Continue the === thing.
if (typeof a !== 'object') return false;
// Prototype checking.
if (!Object.is(
Object.getPrototypeOf(a),
Object.getPrototypeOf(b),
)) return false;
// Checking the value.
if (Object.is(Object.getPrototypeOf(a), Object)) {
// fallthrough, this is just faster
} else if (Array.isArray(a)) {
if (a.length !== b.length) return false;
// Check all the values.
for (let i = a.length - 1; i > -1; --i) {
if (!ocom(a[i], b[i])) return false;
}
return true;
} else if (a instanceof Map) {
// Pass the load to the array handler.
return ocom(
a.entries().toArray(),
b.entries().toArray(),
);
} else if (a instanceof Set || a instanceof ocom.TypedArray) {
return ocom(Array.from(a), Array.from(b));
} else if (a instanceof DataView || a instanceof ArrayBuffer) {
if (a instanceof DataView) {
a = a.buffer;
b = b.buffer;
}
return ocom(Array.from(new Uint8Array(a)), Array.from(new Uint8Array(b)));
}
const keysA = Object.getOwnPropertyNames(a).concat(Object.getOwnPropertySymbols(a));
const keysB = Object.getOwnPropertyNames(b).concat(Object.getOwnPropertySymbols(b));
if (keysA.length !== keysB.length) return false;
for (let i = keysA.length - 1; i > -1; --i) {
if (!ocom(keysA[i], keysB[i])) return false;
}
const valsA = Object.values(a);
const valsB = Object.values(b);
if (valsA.length !== valsB.length) return false;
for (let i = valsA.length - 1; i > -1; --i) {
if (!ocom(valsA[i], valsB[i])) return false;
}
return true;
}
ocom.TypedArray = Object.getPrototypeOf(Uint8Array);
ocom.matcher = Symbol('ObjectCompare.customMatch');
console.log(ocom({ x: 1 }, { x: 1 }));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment