4 creative ways to clone objects

There are a lot of ways to clone objects in Javascript, and some of them get pretty creative. jQuery has an excellent method for cloning objects, as does Mootools. There’s a Javascript hack we can sort of “exploit”, or we could just clone our object in plain Javascript. Let’s start with the vanilla Javascript first and move on from there.

1) A vanilla Javascript method for cloning objects

This is a somewhat simple function that will clone an object and return the clone. If a non-object value is passed in, that value is returned.

// recursive function to clone an object. If a non object parameter
// is passed in, that parameter is returned and no recursion occurs.

function cloneObject(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}

var temp = obj.constructor(); // give temp the original obj's constructor
for (var key in obj) {
temp[key] = cloneObject(obj[key]);
}

return temp;
}

var bob = {
name: "Bob",
age: 32
};

var bill = (cloneObject(bob));
bill.name = "Bill";

console.log(bob);
console.log(bill);

If you try the above function, you’ll see that once bob has been cloned as bill, modifying values on bill won’t change the original values on bob.

2) A clever exploit of the JSON library to deep-clone objects

We can exploit the JSON library for a rather fast way of deep-cloning objects. Check it out:

var bob = {
name: "Bob",
age: 32
};

var bill = (JSON.parse(JSON.stringify(bob)));
bill.name = "Bill";

console.log(bob);
console.log(bill);

This method is nice and fast (faster as a rule than the jQuery method and possibly the Mootools function as well), and certainly rather less code than the first example. Plus, it’s pretty clever–just make sure you add a comment explaining what you’re doing. Otherwise, it could cause quite a bit of confusion!

3) Using jQuery’s $.extend() function

jQuery has a method that can be used to deep-clone objects, the $.extend() function. Let’s take a look at how it can be used:

var bob = {
name: "Bob",
age: 32
};

var bill = $.extend(true, {}, bob);
bill.name = "Bill";

console.log(bob);
console.log(bill);

Pretty handy, eh? This method is a little slower than the JSON exploit, but that shouldn’t really be a problem when you’re only doing a few clones. If you’re doing hundreds or thousands of clones, it might be time to think about the JSON exploit or another solution.

4) Using Mootools’ clone() function to clone objects

Last but not least, the Javascript library Mootools also provides a means of cloning objects–the rather aptly named clone() function. Observe the wild clone() in its natural habitat:

var bob = {
name: "Bob",
age: 32
};

var bill = Object.clone(bob);
bill.name = "Bill";

console.log(bob);
console.log(bill);

23 thoughts on “4 creative ways to clone objects”

  1. Anonymous says:

    Great article – just a few notes about your vanilla function:I think you mean `new obj.constructor`, because you’re not creating an instance otherwise (just happens to work with your `Object` example, though).

    Also an `undefined` value doesn’t work – I recommend `!obj` instead of the `null` check, since all falsy values are not objects anyway.

    (Note that recursive objects like `obj.foo = obj` also won’t work but that’s not interesting, usually.)

  2. Andreas Niedermair says:

    Greate article – one critical thing is missing although: Have you ever tried to clone a `Date`-instance? … well `$.extend()` isn’t able to handle this … just btw :)

  3. admin says:

    @Anonymous: Good points–you’re correct on both counts. Thanks for the catches!@Andreas: No, I can’t say I’ve ever tried to clone a Date instance with $.extend(). To be honest, I can’t imagine why I would need to! However, I will make a note of that, thanks for pointing this out. :-)

  4. John Miller says:

    Thanks for your clear and comprehensive analysis – particularly for drawing attention to the clever (and very effective) exploit of JSON.

  5. admin says:

    You’re welcome, John! I hope this helped a little. :)

  6. K D says:

    Thanks Elliot. Great Article.I knew the 1st and 3rds but it extended my knowledge. Great use of existing stuffs.

    Cheers,KD

  7. admin says:

    Awesome, glad it helped.

  8. Alk says:

    Why have you not considered ‘Object.create()’ though? Are there any serious drawbacks to using that?

  9. Balu says:

    Awesome, it helped.

  10. Geoff Abbott says:

    JSON exploit is $$

  11. wdog says:

    var obj1, obj2, obj3;
    obj1 = { number : 2 }
    obj2 = obj1;

    // THIS MODIFY OBJ1 ALSO

    obj2.number= 3;
    console.log(‘value of orginal object’);
    console.log(obj1.number);

    // THIS NOT MODIFY OBJ1
    obj3 = Object.create(obj2)
    obj3.number= 4;

    console.log(‘value of orginal object’);
    console.log(obj1.number);

    is this way wrong? Object.create()?

    1. elliotbonneville says:

      Well, if you’re trying to clone obj1 it’s not going to do what you think. Have a look at what the Object.create function actually does–obj3 becomes a new object with obj1 as its prototype, so if you change obj1 those properties (if unchanged on obj3) will be changed as well.

  12. Ismael says:

    Where can I found documentation about “constructor()” function, not “constructor” propertie ?

  13. Ismael says:

    In the option 1). Why does it have to be recursive?
    I mean if a change

    temp[key] = cloneObject(obj[key]);

    for
    temp[key] = obj[key];

    It works

    1. elliotbonneville says:

      If you have an object that is a property of another object, it won’t copy over properly if it’s not recursive.

  14. Borja says:

    You should be aware about JSON “exploit”. As JSON does not stores any function, you will lose them if you apply this method.You must use an the first method instead of using that JSON “exploit”. If you want to go further, you can add that first function as an Object prototype function, using something like this:

    Object.prototype.clone = function(obj){
    var src = obj || this;
    var res = {};
    var kType;
    var kVal;
    for(var k in src){
    kVal = src[k];
    kType = typeof kVal;
    if(k !== ‘clone’){
    if(kType === ‘object’){
    res[k] = kVal.clone();
    }else{
    res[k] = kVal;
    }
    }
    }
    return res;
    }

  15. Serghei says:

    first example is wrong for this case:

    function X(arg1) {
    if(arg1 == undefined) throw new Error()
    }

  16. AlvaroPinot says:

    Take into consideration that JSON.stringify could fail with objects having circular references.