Implement deepClone
Write deepClone(value) that returns a deep copy of value, so changing the copy never affects the original. It should handle:
- primitives such as
42,'text',nullandundefined, which are returned as they are - plain objects and arrays, nested to any depth
Date,MapandSet(the values inside aMaporSetare cloned deeply too)- circular references: if
obj.self === obj, thencopy.self === copy
If the same object appears in several places, the copy should reuse a single clone of it, mirroring the original structure.
deepClone({ a: [1, { b: 2 }] })→ an equal object whose array and inner object are newdeepClone(new Map([['k', { n: 1 }]]))→ a newMapholding a new{ n: 1 }deepClone(new Date(0))→ a newDatewith the same time
Define deepClone in the editor. 7 tests will call it.
Hint 1Return primitives (and null) straight away; only objects need copying. Then recurse into every key of objects and arrays.
Hint 2Treat Date, Map and Set separately: create a new instance and copy the contents, cloning every value recursively. JSON.parse(JSON.stringify(x)) loses all three.
Hint 3For cycles, keep a WeakMap from each original object to its copy. Store the copy before recursing into children, and return the stored copy whenever you meet an object you've already seen.
one clean solution
function deepClone(value, seen = new WeakMap()) {
if (value === null || typeof value !== 'object') return value;
if (seen.has(value)) return seen.get(value);
if (value instanceof Date) return new Date(value.getTime());
if (value instanceof Map) {
const copy = new Map();
seen.set(value, copy);
value.forEach((v, k) => copy.set(k, deepClone(v, seen)));
return copy;
}
if (value instanceof Set) {
const copy = new Set();
seen.set(value, copy);
value.forEach((v) => copy.add(deepClone(v, seen)));
return copy;
}
const copy = Array.isArray(value) ? [] : Object.create(Object.getPrototypeOf(value));
seen.set(value, copy); // register before recursing so cycles point back to the copy
for (const key of Object.keys(value)) {
copy[key] = deepClone(value[key], seen);
}
return copy;
}