Last active
May 25, 2020 19:16
-
-
Save c7x43t/38afee87bb7391efb9ac27a3c282e5ed to your computer and use it in GitHub Desktop.
Deep Copy an object very fast
This file contains 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
// deep copy: | |
// String, Number, undefined, null, Set, Map, typed Array, Object, Boolean, RegExp, Date, ArrayBuffer, Node | |
// Functions, Properties of types: (Primitive, Symbol) | |
// shallow copy (by reference): | |
// WeakMap, WeakSet, Symbol | |
// increased compatibility: IE, Node | |
var $jscomp = $jscomp || {}; | |
$jscomp.scope = {}; | |
$jscomp.ASSUME_ES5 = !1; | |
$jscomp.defineProperty = $jscomp.ASSUME_ES5 || "function" == typeof Object.defineProperties ? Object.defineProperty : function(a, b, c) { | |
a != Array.prototype && a != Object.prototype && (a[b] = c.value) | |
}; | |
$jscomp.getGlobal = function(a) { | |
return "undefined" != typeof window && window === a ? a : "undefined" != typeof global && null != global ? global : a | |
}; | |
$jscomp.global = $jscomp.getGlobal(this); | |
$jscomp.SYMBOL_PREFIX = "jscomp_symbol_"; | |
$jscomp.initSymbol = function() { | |
$jscomp.initSymbol = function() {}; | |
$jscomp.global.Symbol || ($jscomp.global.Symbol = $jscomp.Symbol) | |
}; | |
$jscomp.Symbol = function() { | |
var a = 0; | |
return function(b) { | |
return $jscomp.SYMBOL_PREFIX + (b || "") + a++ | |
} | |
}(); | |
$jscomp.initSymbolIterator = function() { | |
$jscomp.initSymbol(); | |
var a = $jscomp.global.Symbol.iterator; | |
a || (a = $jscomp.global.Symbol.iterator = $jscomp.global.Symbol("iterator")); | |
"function" != typeof Array.prototype[a] && $jscomp.defineProperty(Array.prototype, a, { | |
configurable: !0, | |
writable: !0, | |
value: function() { | |
return $jscomp.arrayIterator(this) | |
} | |
}); | |
$jscomp.initSymbolIterator = function() {} | |
}; | |
$jscomp.arrayIterator = function(a) { | |
var b = 0; | |
return $jscomp.iteratorPrototype(function() { | |
return b < a.length ? { | |
done: !1, | |
value: a[b++] | |
} : { | |
done: !0 | |
} | |
}) | |
}; | |
$jscomp.iteratorPrototype = function(a) { | |
$jscomp.initSymbolIterator(); | |
a = { | |
next: a | |
}; | |
a[$jscomp.global.Symbol.iterator] = function() { | |
return this | |
}; | |
return a | |
}; | |
function deepCopy(o) { | |
if ((typeof o !== "object" || o === null) && !(o instanceof Function)) return o; // fast obj/null test | |
let n, keys; | |
const c = o.constructor; | |
$jscomp.initSymbol(); | |
$jscomp.initSymbolIterator(); | |
if (o[Symbol.iterator] instanceof Function) { // fast array test | |
// Map and Set have no length property so they will be correctly constructed | |
const l = o.length; | |
n = (new c(l)); | |
switch (c.name) { | |
case "Set": | |
for (let e of o) n.add(deepCopy(e)); | |
break; | |
case "Map": | |
for (let [key, value] of o) n.set(key, deepCopy(value)); | |
break; | |
} | |
for (let i of Object.keys(o)) n[i] = deepCopy(o[i]); | |
} else { | |
if (c.name !== "Object") { | |
switch (c.name) { | |
case "Function": | |
let str = o.toString(); | |
if(/ \[native code\] /.exec(str) === null){ | |
let args=/^.*?\((.*?)\)/.exec(str)[1];//.split(/,/); | |
let func=/^.*?{(.*)}/.exec(str)[1]; | |
n=new c(args,func); | |
}else{ | |
n=o; | |
} | |
break; | |
case "RegExp": | |
n = new c(o.valueOf()); | |
break; | |
case "Date": | |
n = new c(o); | |
break; | |
case "ArrayBuffer": | |
n = new c((new $jscomp.global["Int8Array"](o)).length); | |
break; | |
default: | |
n = o instanceof Node? o.cloneNode(true) : o; | |
} | |
keys = Object.keys(o); | |
} else { | |
n = {}; | |
keys = Object.getOwnPropertyNames(o); | |
} | |
for (let i of keys) n[i] = deepCopy(o[i]); | |
} | |
if(Object.getOwnPropertySymbols){ | |
for (let i of Object.getOwnPropertySymbols(o)) n[i] = deepCopy(o[i]); | |
} | |
return n; | |
} |
This file contains 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
function deepCopy(a){if(("object"!=typeof a||null===a)&&!(a instanceof Function))return a;let b,d;const f=a.constructor;if(a[Symbol.iterator]instanceof Function){const g=a.length;switch(b=new f(g),f){case Set:for(let h of a)b.add(deepCopy(h));break;case Map:for(let[h,j]of a)b.set(h,deepCopy(j));}for(let h of Object.keys(a))b[h]=deepCopy(a[h])}else if(d=Object.getOwnPropertyNames(a),f!==Object){switch(f){case Function:let g=a.toString();b=null===/ \[native code\] /.exec(g)?new f(/^.*?{(.*)}/.exec(g)[1]):a;break;case RegExp:b=new f(a.valueOf());break;case Date:b=new f(a);break;case ArrayBuffer:b=new f(new Int8Array(a).length);break;default:b=a;}for(let g of d)b.hasOwnProperty(g)||(b[g]=deepCopy(a[g]))}else{b={};for(let g of d)b[g]=deepCopy(a[g])}for(let g of Object.getOwnPropertySymbols(a))b[g]=deepCopy(a[g]);return b} |
This file contains 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
// fully compatible with deepCopy of https://www.npmjs.com/package/deepcopy | |
// except ArrayBuffer | |
var arr = [1, 2, 3, 4, 5, 6, 7, 8]; | |
var list = ["a", 3, {}, [], null, undefined, /a/, Symbol(), new Date(), true, new ArrayBuffer(10), new Float32Array(arr), | |
new Float64Array(arr), new Int16Array(arr), new Int32Array(arr), new Int8Array(arr), new Uint16Array(arr), | |
new Uint32Array(arr), new Uint8Array(arr), new Uint8ClampedArray(arr), new Set(arr), new Map([ | |
[1, 1], | |
[2, 2], | |
[3, 3] | |
]), new WeakSet([Array, Map, Set]), new WeakMap([ | |
[Array, 1], | |
[Map, 2], | |
[Set, 3] | |
]), | |
document.createElement("p") | |
]; | |
var types = list.map(e => e && e.constructor); | |
var clist = deepCopy(list); | |
var ctypes = clist.map(e => e && e.constructor); | |
var diff = []; | |
types.map((e, i) => { | |
if (e !== ctypes[i]) { | |
diff.push(e) | |
} | |
}); | |
diff; | |
function deepCopy(o) { | |
if (typeof o !== "object" || o === null) return o; // fast obj/null test | |
let n; | |
const c = o.constructor; | |
if (o[Symbol.iterator] instanceof Function) { // fast array test | |
// Map and Set have no length property so they will be correctly constructed | |
const l = o.length; | |
n = (new c(l)); | |
switch (c) { | |
case Array: | |
for (let i = 0; i < l; i++) n[i] = deepCopy(o[i]); | |
break; | |
case Set: | |
for (let e of o) n.add(deepCopy(e)); | |
break; | |
case Map: | |
for (let [key, value] of o) n.set(key, deepCopy(value)); | |
break; | |
default: | |
for (let i = 0; i < l; i++) n[i] = o[i]; | |
} | |
return n; | |
} | |
//if (c === RegExp || c === Date || c === WeakMap || c === WeakSet) | |
if (c !== Object) return o; | |
n = {}; | |
for (let i in o) | |
if (o.hasOwnProperty(i)) n[i] = deepCopy(o[i]); // fast hasProperty test | |
return n; | |
} | |
/* OLD: | |
function deepCopy(o) { | |
if (typeof o !== "object" || o === null) return o; // fast obj/null test | |
let n; | |
if (o instanceof Array) { // fast array test | |
const l = o.length; | |
n = []; | |
for (let i = 0; i < l; i++) n[i] = deepCopy(o[i]); | |
return n | |
} | |
n = {}; | |
for (let i in o) | |
if (o.hasOwnProperty(i)) n[i] = deepCopy(o[i]); // fast hasProperty test | |
return n | |
} | |
*/ |
This file contains 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
// deep copy: | |
// String, Number, undefined, null, Set, Map, typed Array, Object, Boolean, RegExp, Date, ArrayBuffer | |
// Functions, Properties of types: (Primitive, Symbol) | |
// shallow copy (by reference): | |
// WeakMap, WeakSet, Symbol | |
function deepCopy(o) { | |
if ((typeof o !== "object" || o === null) && !(o instanceof Function)) return o; // fast obj/null test | |
let n, keys; | |
const c = o.constructor; | |
if (o[Symbol.iterator] instanceof Function) { // fast array test | |
// Map and Set have no length property so they will be correctly constructed | |
const l = o.length; | |
n = (new c(l)); | |
switch (c) { | |
case Set: | |
for (let e of o) n.add(deepCopy(e)); | |
break; | |
case Map: | |
for (let [key, value] of o) n.set(key, deepCopy(value)); | |
break; | |
} | |
for (let i of Object.keys(o)) n[i] = deepCopy(o[i]); | |
} else { | |
if (c !== Object) { | |
switch (c) { | |
case Function: | |
let str = o.toString(); | |
if(/ \[native code\] /.exec(str) === null){ | |
let args=/^.*?\((.*?)\)/.exec(str)[1];//.split(/,/); | |
let func=/^.*?{(.*)}/.exec(str)[1]; | |
n=new c(args,func); | |
}else{ | |
n=o; | |
} | |
break; | |
case RegExp: | |
n = new c(o.valueOf()); | |
break; | |
case Date: | |
n = new c(o); | |
break; | |
case ArrayBuffer: | |
n = new c((new Int8Array(o)).length); | |
break; | |
default: | |
n = o; | |
} | |
keys = Object.keys(o); | |
} else { | |
n = {}; | |
keys = Object.getOwnPropertyNames(o); | |
} | |
for (let i of keys) n[i] = deepCopy(o[i]); | |
} | |
for (let i of Object.getOwnPropertySymbols(o)) n[i] = deepCopy(o[i]); | |
return n; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment