42

Possible Duplicate:
What is the most efficient way to clone a JavaScript object?

I have an object like this:

User = {    
  name: "user",
  settings: {
    first: "1",
    second: "2"    
  }    
}

and a second one:

user1 = {
  name: "user1",
  settings: {
    second: "3"
  }
}

now I want to copy user1's custom values into User, using:

    for(var key in user1){
        User[key] = user1[key];
    }

the result User will be:

User = {
  name: "user1",
  settings: {
    second: "3"
  }
}

User.settings has been entirely replace while I wanted only settings.second to be replaced.

How to achieve this, without knowing how much child object the main object have?

4
  • 2
    Use recursion? Have you searched for deep Object.copy functions? Commented Jul 2, 2012 at 18:42
  • Because of how javascript passes objects around (by reference), deep copying a nested object is actually quite an ordeal. I'd follow @Bergi's advice and find a pre-existing one. Commented Jul 2, 2012 at 18:55
  • 2
    "This question has been asked before and already has an answer." So I ask to the moderators, where? Where has it been asked before? Why do you put the burden on the user to dig around and find it? Commented May 15, 2014 at 21:29
  • would this implementation do the work? Commented Nov 10, 2014 at 4:44

3 Answers 3

17

I've found that the best way to go is this:

http://andrewdupont.net/2009/08/28/deep-extending-objects-in-javascript/

Object.deepExtend = function(destination, source) {
  for (var property in source) {
    if (typeof source[property] === "object" &&
     source[property] !== null ) {
      destination[property] = destination[property] || {};
      arguments.callee(destination[property], source[property]);
    } else {
      destination[property] = source[property];
    }
  }
  return destination;
};


Object.extend(destination, source);

What about this?

    function clone(destination, source) {
        for (var property in source) {
            if (typeof source[property] === "object" && source[property] !== null && destination[property]) { 
                clone(destination[property], source[property]);
            } else {
                destination[property] = source[property];
            }
        }
    };
Sign up to request clarification or add additional context in comments.

6 Comments

arguments.callee is deprecated. You should really use a named function. Also, you forgot about hasOwnProperty which is quite essential.
Yes, although you still copy properties from the prototype. And copying to a destination object really should be called "extend", not "clone" (the "deepextend" from your first try would be even better)
My solution accounts for all of this ;) A plus one would be nice, atleast.
what about arrays (with nested objects)?
|
5

Grabbed jQuery's extend method, and made it library agnostic.

Gist: Library agnostic version of jQuery's Extend

Its wrapped in an Extender constructor, so you don't have to instantiate all of its internal methods each time you call the extend method.

Disclaimer: I have not tested this extensively. It's basically a 1:1 clone of jQuery's extend(), however your mileage may vary.

Use it like this.

var user1 = {
  name: "user1",
  settings: {
    first: "1",
      second: {bar: 'foo'}
  }
};
var user2 = {
  name: "user2",
  settings: {
    second: {foo:'bar'}
  }
};

/* merge user1 into User */
__extend(true, user1, user2);

// Modifies the User object
user1.settings.second.foo == 'bar'; // true

// note, you can do assignment too.
var newUser = __extend(true, user1, user2);

See here for more documentation

2 Comments

This might be lengthier than other solutions but it works reliably, and works on both array and object types. Thank you!
This helped me in rhino .. cheers
-1

This is really hacky, but this should work. I suggest doing as the other users have suggested in the comments; find a pre-existing library that will do this for you.

for(var key in user1){  
   var temp = User[key]
   User[key] = user1[key];   
   for(var key1 in temp){
      if(User[key][key1] == null){
         User[key][key1] = temp[key1];
      }
   }
}

4 Comments

the object i posted was an example i'm in search of something that will work everywhere
O ok. Well I would take a look at jQuerys api.jquery.com/jQuery.extend, it looks like it may do exactly what your looking for.
i've found this which seems to be working (not perfect but a start) my.opera.com/GreyWyvern/blog/show.dml/1725165, for jquery I'd like to kkep it framework agnostic
Be aware that this is very simple approach and you may run into some limitations - described here stackoverflow.com/questions/8092548/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.