Implement Deep Clone
Looks simple, but the edge cases are what separate juniors from seniors.
Naive Version
const clone = JSON.parse(JSON.stringify(obj));Problems: Loses functions, undefined, Symbols, Dates (become strings), RegExp, Maps, Sets. Crashes on circular references.
Production Version
function deepClone(value, seen = new WeakMap()) {
if (value === null || typeof value !== 'object') return value;
if (value instanceof Date) return new Date(value.getTime());
if (value instanceof RegExp) return new RegExp(value.source, value.flags);
if (value instanceof Map) {
const map = new Map();
seen.set(value, map);
value.forEach((v, k) => map.set(deepClone(k, seen), deepClone(v, seen)));
return map;
}
if (value instanceof Set) {
const set = new Set();
seen.set(value, set);
value.forEach((v) => set.add(deepClone(v, seen)));
return set;
}
if (seen.has(value)) return seen.get(value);
const clone = Array.isArray(value) ? [] : Object.create(Object.getPrototypeOf(value));
seen.set(value, clone);
for (const key of Reflect.ownKeys(value)) {
const descriptor = Object.getOwnPropertyDescriptor(value, key);
if (descriptor) {
Object.defineProperty(clone, key, {
...descriptor,
value: deepClone(descriptor.value, seen),
});
}
}
return clone;
}Key Points
- Circular references â
WeakMaptracks visited objects to break cycles - Special types â Date, RegExp, Map, Set each need specific handling
- Symbol keys â
Reflect.ownKeyscaptures them unlikeObject.keys - Prototype chain â
Object.create(Object.getPrototypeOf())preserves it - Property descriptors â preserves getters, setters, and non-enumerable properties
Modern Alternative
const clone = structuredClone(value);structuredClone handles circular references, most built-in types, and is the modern standard. But it still can't clone functions, DOM nodes, or property descriptors.
The best answer acknowledges
structuredCloneexists, then demonstrates you understand the underlying mechanics by implementing it manually.