3

Looking for ways to deep copy objects that contain nested and circular structures, neither of these (1, 2, 3, 4) had the perfect solution when it comes to circular references and prototypal inheritance.

I've written my own implementation here. Does it do the job well or count as a better solution?

 /*
    a function for deep cloning objects that contains other nested objects and circular structures.
    objects are stored in a 3D array, according to their length (number of properties) and their depth in the original object.
                                    index (z)
                                         |
                                         |
                                         |
                                         |
                                         |
                                         |                      depth (x)
                                         |_ _ _ _ _ _ _ _ _ _ _ _
                                        /_/_/_/_/_/_/_/_/_/
                                       /_/_/_/_/_/_/_/_/_/
                                      /_/_/_/_/_/_/...../
                                     /................./
                                    /.....            /
                                   /                 /
                                  /------------------
            object length (y)    /
*/


function deepClone(obj) {
    var i = -1, //depth of the current object relative to the passed 'obj'
        j = 0;  //number of the object's properties
    var arr = new Array(); //3D array to store the references to objects
    return clone(obj, arr, i, j);
}

function clone(obj, arr, i ,j){
    if (typeof obj !== "object") {
        return obj;
    }

    var result = Object.create(Object.getPrototypeOf(obj)); //inherit the prototype of the original object
    if(result instanceof Array){
        result.length = Object.keys(obj).length;
    }

    i++; //depth is increased because we entered an object here
    j = Object.keys(obj).length; //native method to get the number of properties in 'obj'
    arr[i] = new Array(); //this is the x-axis, each index here is the depth
    arr[i][j] = new Array(); //this is the y-axis, each index is the length of the object (aka number of props)
    //start the depth at current and go down, cyclic structures won't form on depths more than the current one
    for(var depth = i; depth >= 0; depth--){
        //loop only if the array at this depth and length already have elements
        if(arr[depth][j]){
            for(var index = 0; index < arr[depth][j].length; index++){
                if(obj === arr[depth][j][index]){
                    return obj;
                }
            } 
        }
    }

    arr[i][j].push(obj); //store the object in the array at the current depth and length
    for (var prop in obj) {
        result[prop] = clone(obj[prop], arr, i, j);
    }

    return result;
}
5
  • Have you tried the structured clone algorithm? Commented Nov 12, 2014 at 1:18
  • @Ja͢ck had a glance at that before. I believe it doesn't deal with circular structures, right? Commented Nov 12, 2014 at 1:21
  • plus, you need to manually implement the special cases (e.g. Date, Array, etc.) Commented Nov 12, 2014 at 1:22
  • 1
    Right in the first paragraph the page that describes the structured clone algorithm mentions cyclic graphs. Basically this problem is the well studied graph traversal problem. Commented Nov 12, 2014 at 1:30
  • @akonsu I was reading through its pseudo implementation. Which one you think would be faster? 3D array, as I approached it, or a map, as they approached? Commented Nov 12, 2014 at 1:42

1 Answer 1

0

Can you try the below simple logic. Convert js object into new String and again convert as object.

E.g:

var car = {type:"Fiat", model:"500", color:"white"};
var cloneStr = new String(JSON.stringify(car));
var carClone = JSON.parse(cloneStr);
carClone.type = "Maruthi";
alert(JSON.stringify(car)) ;
alert(JSON.stringify(carClone)) ;
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.