Last active
August 30, 2015 20:22
-
-
Save ironboy/4cb7c2388650245bd999 to your computer and use it in GitHub Desktop.
A deep copier for JavaScript
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
/* | |
A deep copier for JavaScript | |
that can handle circular references, | |
copies objects with correct prototypes, | |
copies functions (rather than referencing them), | |
copies non-enumerable properties | |
and copies HTML- and jQuery-elements as references | |
*/ | |
function deepCopy(obj){ | |
// Memory handling circular references | |
var mem = [], mem2 = []; | |
function remem(obj,newObj){ | |
if(!newObj){ | |
return mem2[mem.indexOf(obj)]; | |
} | |
mem.push(obj); | |
mem2.push(newObj); | |
} | |
function clone(obj){ | |
var newObj; | |
// Primitives and stuff we want to copy by reference (DOM els etc) | |
var primitives = [String,Number,Boolean]; | |
typeof HTMLElement != "undefined" && primitives.push(HTMLElement); | |
typeof HTMLCollection != "undefined" && primitives.push(HTMLCollection); | |
typeof jQuery != "undefined" && primitives.push(jQuery); | |
// Find out if this is a "primitive" | |
var primitive = primitives.some(function(x){ | |
if(obj===null || obj===undefined){return true;} | |
return obj === x || | |
obj.constructor === x || | |
obj instanceof x || | |
// old IE:s don't have HTMLElement | |
(typeof HTMLElement == "undefined" && obj.nodeType); | |
}); | |
// Primitive | |
if(primitive){ | |
newObj = obj; | |
} | |
// Circular reference | |
else if(remem(obj)){ | |
return remem(obj); | |
} | |
// Function | |
else if(obj instanceof Function){ | |
eval("newObj = " + obj); | |
} | |
// Array | |
else if(obj instanceof Array){ | |
newObj = []; | |
} | |
// Object | |
else { | |
try { | |
newObj = Object.create(obj.__proto__); | |
} | |
catch(e){ | |
newObj = {}; | |
} | |
} | |
if(!primitive){ | |
// Write to the memory handling circular references | |
remem(obj,newObj); | |
// Recurse / copy properties of non-primitives | |
if(Object.getOwnPropertyNames){ | |
// copy non iteratable props as well | |
Object.getOwnPropertyNames(obj).forEach(function(i){ | |
newObj[i] = clone (obj[i]); | |
}); | |
} | |
else { | |
// old browsers | |
for(var i in obj){ | |
if(!obj.hasOwnProperty(i)){continue;} | |
newObj[i] = clone(obj[i]); | |
} | |
} | |
} | |
return newObj; | |
} | |
return clone(obj); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment