Deep clone objects with circular references
JavaScript
// Deep clone plain data, preserving Date/Map/Set/RegExp and cycles.
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 RegExp) return new RegExp(value.source, value.flags);
if (value instanceof Map) {
const copy = new Map();
seen.set(value, copy);
for (const [key, item] of value) copy.set(deepClone(key, seen), deepClone(item, seen));
return copy;
}
if (value instanceof Set) {
const copy = new Set();
seen.set(value, copy);
for (const item of value) copy.add(deepClone(item, seen));
return copy;
}
const copy = Array.isArray(value) ? [] : Object.create(Object.getPrototypeOf(value));
seen.set(value, copy);
for (const key of Reflect.ownKeys(value)) {
copy[key] = deepClone(value[key], seen);
}
return copy;
}
const source = { name: 'root', when: new Date(0) };
source.self = source;
const copy = deepClone(source);
console.log(copy !== source, copy.self === copy, copy.when instanceof Date); // true true true