Skip to content Skip to sidebar Skip to footer

Duplicate Object In Javascript

I see two ways to duplicate objects 1. var a={c:1} var b=a; alert(b.c);//alert 1 2. var a={c:2}; var b={}; for (i in a) {b[i]=a[i];} alert(b.c);//alert 1 The first are shorter t

Solution 1:

In the first version you don't duplicate/clone the object you simply make a extra reference to it:

var a = { a: 1 };
var b = a;
b.a = 2;

console.log(a.a); // 2;

To clone an object there is numbers of libraries that can do that for you:

var b = $.extend({}, a); // Make a shallow clone (jQuery)var b _.extend({}, a); // Make a shallow clone (underscore.js)var b = $.extend(true, {}, a); // Make a deep clone (jQuery);

Or you can do it natively: Simple clone:

var b = {};
var prop;

for (prop in a) {
    b[prop] = a[prop];
}

Scratch of a deep clone function:

functiondeepClone(obj) {
    var r;
    var i = 0,
    var len = obj.length;
    // string, number, booleanif (typeof obj !== "object") { 
        r = obj;
    }
    // Simple check for arrayelseif ( len ) { 
        r = [];
        for ( ; i < len; i++ ) {
            r.push( deepClone(obj[i]) );
        }
    } 
    // Simple check for dateelseif ( obj.getTime ) { 
        r = newDate( +obj );
    }
    // Simple check for DOM nodeelseif ( obj.nodeName ) { 
        r = obj;
    }
    // Objectelse { 
        r = {};
        for (i in obj) {
            r[i] = deepClone(obj[i]);
        }
    }

    return r;
}

Solution 2:

The first does not create a copy, but just copies the reference, so a and b point towards the same object after the operation.

In the second case, however, each attribute is copied separately, thus creating a "real" copy of the object in a (as long as there are just primitive types in the properties, else you got the same problem at a deeper level).

So in the first case if you change b.c then a.c will also change, while in the second case it wont.

Solution 3:

As others have stated here: the first assignment, assigns a new reference to an existing object, the second performs a shallow copy.By shallow I mean: only the base object will be copied, there is no recursion:

var a = {some:'propery',
         another:{might:'be',
                  an: 'object, too'}
        };
var b = {};
for(var p in a)
{
    b[p] = a[p];
}
b.some = 'b\'s own property';
console.log(a.some);//property -> unalteredconsole.log(b.some);//b's own property --> separate entities
b.another.might = 'foo';
console.log(a.another.might);//foo ==> b.another references a.another

To solve this issue, you would be forgiven to think that a simple recursive function would suffice:

var cloneObj = function(o)
{
    var p,r = {};
    for (p in o)
    {//omitting checks for functions, date objects and the like
        r[p] = (o[p] instanceofObject ? cloneObj(o[p]) : o[p]);
    }
};

But be weary of circular references!

//assume a is the same object as above
a._myself = a;//<- a references itself

This will produce endless recursion, aka a deadlock scenario, unless you add a check for just such cases:

var cloneObj = function(o)
{
    var p,r = {};
    for (p in o)
    {//Needs a lot more work, just a basic example of a recursive copy functionswitch(true)
        {
            case o[p] instanceofFunction:
                r[p] = o[p];
            break;
            case o[p] instanceofDate:
                r[p] = newDate(o[p]);
            break;
            case o === o[p]:
            //simple circular references only//a.some.child.object.references = a; will still cause trouble
                r[p] = r;
            break;
            case o[p] instanceofArray:
                r[p] = o[p].slice(0);//copy arraysbreak;
            default:
                r[p] = o[p] instanceofObject ? cloneObj(o[p]) : o[p];
        }
    }
    return r;
};

Now, this is quite verbose, and in most cases utter overkill, if all you want are two objects with the same data, but can be altered independently (ie don't reference the same object in memory), all you need is 1 line of code:

var a = {some:'propery',
         another:{might:'be',
                  an: 'object, too'}
        };
var b = JSON.parse(JSON.stringify(a));

Bottom line: assigning a reference is certainly more efficient: it doesn't require the object constructor to be called a second time, nor does it require an additional copy of any of the constants. The downside is: you end up with a single object and might inadvertently change/delete something that you assume is still there when you're using the other reference (delete b.some;/*some time later*/a.some.replace(/p/g,'q');//<--error)

Solution 4:

The first copies the reference and does not duplicate the object, the second creates a new reference and then copies the members (which, in turn, if they are references will just copy the references only).

You might want to look at this other SO - Does Javascript equal sign reference objects or clones them?

It's not a question of efficiency it's ultimately about correctness. If you need to share a reference to an object between different code blocks (e.g. so that multiple pieces of code can share the same object) - then you simply rely on the fact that javascript passes by reference.

If, however, you need to copy an object between methods - then you might be able to use your simple example in your second code block (if your objects don't have other 'objects' in them), otherwise you might have to implement a deep-clone (see How to Deep clone in javascript, and pay attention to the answer(s) there - it's not a trivial business).

Post a Comment for "Duplicate Object In Javascript"