Last active
March 27, 2021 19:29
-
-
Save WebReflection/031bfab4a19e02e23ba2c2bb75cb2fbe to your computer and use it in GitHub Desktop.
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
const clone = (() => { | |
/*! (c) Andrea Giammarchi - WTFPL */ | |
const toString = {}.toString; | |
const flags = ['global', 'ignoreCase', 'multiline', 'sticky', 'unicode']; | |
const prime = obj => typeof obj === 'object' ? new obj.constructor(obj.valueOf()) : obj; | |
const through = obj => { | |
const descriptors = Object.getOwnPropertyDescriptors(obj); | |
Reflect.ownKeys(descriptors).forEach(key => { | |
const descriptor = descriptors[key]; | |
if ('value' in descriptor) { | |
descriptor.value = clone(descriptor.value); | |
} | |
}); | |
return Object.create( | |
Object.getPrototypeOf(obj), | |
descriptors | |
); | |
}; | |
return obj => { | |
const asString = toString.call(obj); | |
switch (asString) { | |
case '[object Array]': return obj.map(clone); | |
case '[object Date]': return new Date(obj.toISOString()); | |
case '[object Map]': return new Map(obj.entries()); | |
case '[object Object]': return through(obj); | |
case '[object Set]': return new Set(obj.values()); | |
case '[object Promise]': return new Promise((res, rej) => obj.then(res, rej)); | |
case '[object RegExp]': return new RegExp(obj.source, flags.map( | |
flag => obj[flag] ? flag[0] : '' | |
).join('').replace('s', 'y')); | |
case '[object Boolean]': | |
case '[object Number]': | |
case '[object String]': return prime(obj); | |
case '[object Null]': | |
case '[object Undefined]': return obj; | |
} | |
switch (true) { | |
case /Array\]$/.test(asString): return obj.constructor.from(obj); | |
case /^\[object (?:HTML|SVG)/.test(asString): return obj.cloneNode(true); | |
case /^\[object Weak/.test(asString): | |
const w = new obj.constructor; | |
w.get = key => w.has(key) ? w.get(key) : obj.get(key); | |
w.has = key => w.has(key) || obj.has(key); | |
return w; | |
} | |
return through(obj); | |
}; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment