💻
CODE SNIPPET — July 13, 2026Deep Merge & Deep Clone in JS (Circular Ref Detection)When
Object.assign(), spread, and
structuredClone() aren't enough.
deepClone(obj) — Full deep copy via
WeakMap. Preserves Dates, Regexps, Maps, Sets, Errors, TypedArrays, Buffers, custom classes. Detects circular refs.
deepMerge(a, b, options) — Recursive merge with array strategies:
'replace' (default),
'concat' (dedup), or custom
fn(left, right, key).
function deepClone(obj, seen = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj;
if (seen.has(obj)) return seen.get(obj);
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
if (obj instanceof Map) { const m = new Map(); obj.forEach((v,k) => m.set(deepClone(k,seen), deepClone(v,seen))); return m; }
if (obj instanceof Set) { const s = new Set(); obj.forEach(v => s.add(deepClone(v,seen))); return s; }
if (ArrayBuffer.isView(obj)) return obj.slice(0);
const clone = Object.create(Object.getPrototypeOf(obj));
seen.set(obj, clone);
for (const [k, v] of Object.entries(obj)) clone[k] = deepClone(v, seen);
return clone;
}
function deepMerge(a, b, { arrays = 'replace' } = {}) {
const r = { ...a };
for (const [k, v] of Object.entries(b)) {
if (v && typeof v === 'object' && !Array.isArray(v) && a[k] && typeof a[k] === 'object')
r[k] = deepMerge(a[k], v, { arrays });
else if (arrays === 'concat' && Array.isArray(a[k]) && Array.isArray(v))
r[k] = [...new Set([...a[k], ...v])];
else r[k] = v;
}
return r;
}
Zero deps — browsers, Node, Deno. Bookmark for when
structuredClone() isn't available.
\#javascript \#deepmerge \#deepclone