Skip to content

Instantly share code, notes, and snippets.

@ironboy
Last active August 30, 2015 20:22
Show Gist options
  • Save ironboy/4cb7c2388650245bd999 to your computer and use it in GitHub Desktop.
Save ironboy/4cb7c2388650245bd999 to your computer and use it in GitHub Desktop.
A deep copier for JavaScript
/*
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