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 
      };  
                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.
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; })
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With