Skip to content

Instantly share code, notes, and snippets.

@c7x43t
Last active May 25, 2020 19:16
Show Gist options
  • Save c7x43t/38afee87bb7391efb9ac27a3c282e5ed to your computer and use it in GitHub Desktop.
Save c7x43t/38afee87bb7391efb9ac27a3c282e5ed to your computer and use it in GitHub Desktop.
Deep Copy an object very fast
// 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;
}
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}
// 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
}
*/
// 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