Last active
July 26, 2020 08:14
-
-
Save frydlewicz/0c7ed3f08c4cd4b5762f7d8ecf3227ec to your computer and use it in GitHub Desktop.
TypeScript methods cloning and comparing objects using WeakMap and WeakSet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export interface IObject { | |
[key: string]: any; | |
} | |
export function cloneObject(source: IObject, maxDeep: number = Infinity): IObject { | |
if (typeof source !== 'object') { | |
throw new Error('Argument must be an object'); | |
} | |
const refs = new WeakMap<IObject, IObject>(); | |
const dest: IObject = {}; | |
(function deepSearch(dest: IObject, source: IObject, deep: number = 0): void { | |
for (const key of Object.keys(source)) { | |
const node = source[key]; | |
if (node.constructor === Date) { | |
dest[key] = new Date(node); | |
} else if (typeof node !== 'object' || deep >= maxDeep || | |
node.constructor !== Array && node.constructor !== Object) { | |
dest[key] = node; | |
} else { | |
const ref = refs.get(node); | |
if (ref) { | |
dest[key] = ref; | |
} else { | |
if (node.constructor === Array) { | |
dest[key] = []; | |
} else { | |
dest[key] = {}; | |
} | |
refs.set(node, dest[key]); | |
deepSearch(dest[key], node, deep + 1); | |
} | |
} | |
} | |
})(dest, source); | |
return dest; | |
} | |
export function sameObjects(obj1: IObject, obj2: IObject = {}): boolean { | |
if (typeof obj1 !== 'object' || typeof obj2 !== 'object') { | |
throw new Error('Arguments must be objects'); | |
} | |
const refs = new WeakSet<IObject>(); | |
return (function deepSearch(obj1: IObject, obj2: IObject): boolean { | |
for (const key of Object.keys(obj1)) { | |
const type1 = typeof obj1[key]; | |
const type2 = typeof obj2[key]; | |
if (type2 === 'undefined' || type1 !== type2) { | |
return false; | |
} else if (type1 === 'object') { | |
if (!refs.has(obj1[key])) { | |
refs.add(obj1[key]); | |
if (obj1[key].toString() !== obj2[key].toString() || | |
!deepSearch(obj1[key], obj2[key])) { | |
return false; | |
} | |
} | |
} else if (type1 === 'function') { | |
if (obj1[key].toString() !== obj2[key].toString()) { | |
return false; | |
} | |
} else if (obj1[key] !== obj2[key]) { | |
return false; | |
} | |
} | |
return true; | |
})(obj1, obj2); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment