Skip to content

Instantly share code, notes, and snippets.

@jhunterkohler
Last active July 29, 2021 01:07
Show Gist options
  • Save jhunterkohler/64f67c228d99c1b017a556c5daa36620 to your computer and use it in GitHub Desktop.
Save jhunterkohler/64f67c228d99c1b017a556c5daa36620 to your computer and use it in GitHub Desktop.
Deep copy js object
export function deepcopy(value) {
return __deepcopy(value, new WeakMap());
}
export default deepcopy;
const TypedArray = Reflect.getPrototypeOf(Int8Array);
function identity(value) {
return value;
}
function copyprops(source, target, cache) {
for (const property in source) {
target[property] = __deepcopy(source[property], cache);
}
return target;
}
// TODO: Copy only outside keys in wrapped constructors
function __deepcopy(value, cache) {
if (
(typeof value != "object" || value === null) &&
typeof value != "function"
) {
return value;
}
if (cache.has(value)) {
return cache.get(value);
}
let result;
let cached = false;
if (typeof value == "function") {
} else if (value instanceof RegExp) {
result = new RegExp(value);
} else if (value instanceof Map) {
result = new Map();
cache.set(value, result);
cached = true;
for (const [key, val] of value) {
result.set(__deepcopy(key, cache), __deepcopy(val, cache));
}
} else if (value instanceof Set) {
result = new Set();
cache.set(value, result);
cached = true;
for (const val of value) {
result.add(__deepcopy(val, cache));
}
} else if (Buffer.isBuffer(value)) {
result = Buffer.from(value);
} else if (value instanceof Promise) {
result = value.then(identity);
} else if (value instanceof WeakMap || value instanceof WeakSet) {
// TODO: Improve
result = value;
} else if (value instanceof WeakRef) {
// TODO: Decide what to do with empty refs
const target = value.deref();
if (target) {
const copy = __deepcopy(target, cache);
// Should deal with recursive structures
if (cache.has(value)) {
result = cache.get(value);
} else {
result = new WeakRef(copy);
cache.set(value, result);
}
} else {
result = new WeakRef(Object.create(null));
cache.set(value, result);
}
cached = true;
} else if (value instanceof Date) {
result = new Date(value.getTime());
} else if (value instanceof Error) {
result = new Error();
} else if (value instanceof DataView) {
result = new DataView(value.buffer.slice(0));
} else if (value instanceof ArrayBuffer || value instanceof TypedArray) {
result = value.slice(0);
} else if (value instanceof URL) {
result = new URL(value);
} else {
result = {};
}
if (!cached) {
cache.set(value, result);
}
copyprops(value, result, cache);
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment