Last active
July 29, 2021 01:07
-
-
Save jhunterkohler/64f67c228d99c1b017a556c5daa36620 to your computer and use it in GitHub Desktop.
Deep copy js object
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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