7

I have an nested object that I want to update it with values provided by object that contains similar structure but only the properties that I want updated. Creating a new result instead of modifying the initial objects is great too.

    var initial = 
      { 
         a: 1, 
         b : { 
            c : 2, 
            d : 3 
         },
         f: 5 
      }; 

    var update = {
        a: 2,
        b: {
           d: 2
        }
    };         
    function updateFunction (a,b) {  return a+b;};
    var result= 
      { 
         a: 3, // updateFunction (1,2)=> 3
         b : { 
            c : 2, 
            d :5 // updateFunction (3,2) => 5
         },
         f: 5 
      };  
2
  • 1
    Just iterate through properties, if typeof x == 'object' perform recursive call, otherwise compare and assign value if !== ... What kind of issue is there here ? What have you tried ? Commented May 5, 2013 at 12:16
  • The issue was that I thought that objects are passed by value instead of by reference. Commented May 5, 2013 at 12:52

2 Answers 2

5

Have not tested fully, but maybe,

assuming objects are simple as stated,

function updateFunction (a,b) {  return a + b;};    

function recurse(initial, update){
    for(prop in initial){
        if({}.hasOwnProperty.call(initial, prop) && {}.hasOwnProperty.call(update, prop)){
            if(typeof initial[prop] === 'object' && typeof update[prop] === 'object'){
                recurse(initial[prop], update[prop]);
            }
            else{
                initial[prop] = updateFunction(initial[prop], update[prop]);
            }
        }
    }
}
recurse(initial, update);

EDIT

If result is expected without changing initial

function updateFunction (a,b) {  return a + b;};

function recurse(initial, update){
    var result = {};
    for(prop in initial){
        if({}.hasOwnProperty.call(initial, prop)){
            result[prop] = initial[prop];    
            if({}.hasOwnProperty.call(update, prop)){
                if(typeof initial[prop] === 'object' && typeof update[prop] === 'object'){
                    result[prop] = recurse(initial[prop], update[prop]);
                }
                else{
                    result[prop] = updateFunction(initial[prop], update[prop]);
                }
            }
        }    
    }
    return result;
}
var result = recurse(initial, update);

hope this helps.

Sign up to request clarification or add additional context in comments.

7 Comments

Don't forget hasOwnProperty
initial.hasOwnProperty(prop) doesn't cut it - what if one of the keys in my object is hasOwnProperty? You need to use {}.hasOwnProperty.call(initial, prop), as in my answer
Thanks shakib it works great from my needs. I've changed only initial.hasOwnProperty(prop) to {}.hasOwnProperty.call(initial, prop) as per Eric suggestion.
@user1851442 You are welcome. edited the answer with the change.
Note that this modifies the original object, whereas mine creates a copy of the parts it changes.
|
3

Here's how I'd do it:

// The parallel to Array.map
Object.map = function(obj, f) {
    var result = {};
    for(k in obj)
        if({}.hasOwnProperty.call(obj, k))
            result[k] = f(k, obj[k]);
    return result;
}

// Takes two objects and uses `resolve` to merge them
function merge(a, b, resolve) {
    return Object.map(a, function(k, a_value) {
        if(k in b)
            return resolve(a_value, b[k]);
        else
            return a_value;
    });
}

// same as above, but recursing when an object is found
function recursive_merge(a, b, resolve) {
    return merge(a, b, function(a_value, b_value) {
        if(typeof a_value == 'object' && typeof b_value == 'object')
            return recursive_merge(a_value, b_value, resolve);
        else
            return resolve(a_value, b_value);
    });
}

result = recursive_merge(initial, update, function(a, b) { return a + b; })

4 Comments

Nice! Only you might consider cloning a_value objects even if they have no respective property in b - of course, that depends on the OPs exact needs.
@Bergi: I see what you mean
I can't run your code rmerge is not defined, throws error at result = rmerge(initial, update, function(a, b) { return a + b; }) ReferenceError: rmerge is not defined result = merge(initial, update, function(a, b) { return a + b; }) ReferenceError: v is not defined result = recursive_merge(initial, update, function(a, b) { return a + b; })
@user1851442: Whoops - fixed

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.