javascript tutorial - [Solved-5 Solutions] Clone a javascript object - javascript - java script - javascript array



Problem:

How do we correctly clone a JavaScript object?

Solution 1:

if the source's prototype is some descendant of Object, then we are going to be missing the additional members from that prototype which we skipped using the hasOwnProperty filter

function clone(obj) {
    if (null == obj || "object" != typeof obj) return obj;
    var copy = obj.constructor();
    for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
    }
    return copy;
}

var d1 = new Date();

/* Executes function after 5 seconds. */
setTimeout(function(){
    var d2 = clone(d1);
    alert("d1 = " + d1.toString() + "\nd2 = " + d2.toString());
}, 5000);
click below button to copy the code. By JavaScript tutorial team
  • The date string for d1 will be 5 seconds behind that of d2. A way to make one Date the same as another is by calling the setTime method, but that is specific to the Date class. we don't think there is a bullet-proof general solution to this problem, though we would be happy to be wrong!
  • This can be accomplished with code like the following:
function clone(obj) {
    var copy;

    // Handle the 3 simple types, and null or undefined
    if (null == obj || "object" != typeof obj) return obj;

    // Handle Date
    if (obj instanceof Date) {
        copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
    }

    // Handle Array
    if (obj instanceof Array) {
        copy = [];
        for (var we = 0, len = obj.length; we < len; i++) {
            copy[i] = clone(obj[i]);
        }
        return copy;
    }

    // Handle Object
    if (obj instanceof Object) {
        copy = {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
        }
        return copy;
    }

    throw new Error("Unable to copy obj! Its type isn't supported.");
}
click below button to copy the code. By JavaScript tutorial team

The above function will work adequately for the 6 simple types we mentioned, as long as the data in the objects and arrays form a tree structure. That is, there isn't more than one reference to the same data in the object. For example:

// This would be cloneable:
var tree = {
    "left"  : { "left" : null, "right" : null, "data" : 3 },
    "right" : null,
    "data"  : 8
};

// This would kind-of work, but we would get 2 copies of the 
// inner node instead of 2 references to the same copy
var directedAcylicGraph = {
    "left"  : { "left" : null, "right" : null, "data" : 3 },
    "data"  : 8
};
directedAcyclicGraph["right"] = directedAcyclicGraph["left"];

var cylicGraph = {
    "left"  : { "left" : null, "right" : null, "data" : 3 },
    "data"  : 8
};
cylicGraph["right"] = cylicGraph;

click below button to copy the code. By JavaScript tutorial team

Solution 2:

With jQuery, we can shallow copy with

var copiedObject = jQuery.extend({}, originalObject)
click below button to copy the code. By JavaScript tutorial team

subsequent changes to the copiedObject will not affect the origina lObject, and vice versa.

Or to make a deep copy:

var copiedObject = jQuery.extend(true, {}, originalObject)
click below button to copy the code. By JavaScript tutorial team

Solution 3:

If we do not use functions within your object, a very simple one liner can be the following:

var cloneOfA = JSON.parse(JSON.stringify(a));
click below button to copy the code. By JavaScript tutorial team
  • This works for all kind of objects containing objects, arrays, strings, booleans and numbers.
  • See also this article about the structured clone algorithm of browsers which is used when posting messages to and from a worker. It also contains a function for deep cloning.

Solution 4:

In ECMAScript 6 there is Object.assign method, which copies values of all enumerable own properties from one object to another. For example:

var x = {myProp: "value"};
var y = Object.assign({}, x); 
click below button to copy the code. By JavaScript tutorial team

But be aware that nested objects are still copied as reference.

Solution 5:

There are many answers, but none that mentions Object.create from ECMAScript 5, which admittedly does not give we an exact copy, but sets the source as the prototype of the new object.

Thus, this is not an exact answer to the question, but it is a one-line solution and thus elegant. And it works best for 2 cases:

  • Where such inheritance is useful (duh!)
  • Where the source object won't be modified, thus making the relation between the 2 objects a non issue.

Example:

var foo = { a : 1 };
var bar = Object.create(foo);
foo.a; // 1
bar.a; // 1
foo.a = 2;
bar.a; // 2 - prototype changed
bar.a = 3;
foo.a; // Still 2, since setting bar.a makes it an "own" property
click below button to copy the code. By JavaScript tutorial team

Why do we consider this solution to be superior? It's native, thus no looping, no recursion. However, older browsers will need a polyfill.


Related Searches to javascript tutorial - Clone a javascript object