I have underscore.
I have:
var person = {
  personal: {
    fname: 'Victor',
    lname: 'Lee',
    address: {
      street: '1234 Main',
      state: {
        abbrName: 'CA',
        fullName: 'California',
        timezone: 'PST'
      },
      zip: '94043'
    }
  }
};
I would like to update multiple properties but leave others untouched.
Instead of writing three seperate lines:
  person.personal.address.state.abbrName = 'OR';
  person.personal.address.state.fullName = 'Oregon';
  person.personal.address.zip = '97062';
I want to be able to set all props in one line of code, but also leave other properties untouched.
If I do:
_.extend(person.personal.address, {
  state: {
    abbrName: 'OR',
    fullName: 'Oregon'
  },
  zip: '97032'
});
The resulting object has the time zone hacked out:
{
  personal: {
    fname: 'Victor',
    lname: 'Lee',
    address: {
      street: '1234 Main',
      state: {
        abbrName: 'CA',
        fullName: 'California',
      },
      zip: '94043'
    }
  }
};
Something like this would be ideal:
var updateObj = function(obj, key, value){
  // stuff
  return obj;
};
and run like:
updateObj(person, 'personal.address', {
  state: {
    abbrName: 'OR',
    fullName: 'Oregon'
  },
  zip: '97032'
});
So far I've got this but it only completely overwrites one property at a time.
var updateObjectWithStringKey = function(obj, key, value) {
  if (typeof key === "string"){
    key = key.split(".");
  };
  if (prop.length > 1) {
    var e = key.shift();
    updateObjectWithStringKey(obj[e] =
      typeof obj[e] == 'object' ? obj[e] : {},
      key,
      value);
  } else {
    obj[key[0]] = value;
  };
  return obj;
};
EDIT
Ok, I think I'm getting close:
var MergeRecursive = function(destination, source) {
  for (var p in source) {
    if ( typeof source[p] == 'object' ) {
      destination[p] = MergeRecursive(destination[p], source[p]);
    } else {
      destination[p] = source[p];
    };
  };
  return destination;
};
This merges information even if its wedged between levels in an object:
var person = {
  personal: {
    fname: 'Victor',
    lname: 'Lee',
    address: {
      street: '1234 Main',
      state: {
        abbrName: 'CA',
        fullName: 'California',
        timezone: 'PST'
      },
      zip: '94043'
    }
  }
};
var updatedInfo = {
  personal: {
    address: {
      state: {
        abbrName: 'OR',
        fullName: 'Oregon',
        capital: 'Salem'
      },
      zip: '97062'
    },
  }
};
MergeRecursive(person, updatedInfo);
returns
{
  personal: {
    fname: 'Victor',
    lname: 'Lee',
    address: {
      street: '1234 Main',
      state: {
        abbrName: 'OR',
        fullName: 'Oregon',
        timezone: 'PST',
        capital: 'Salem'
      },
      zip: '97062'
    }
  }
}
But like I said, I would like to provide a string path to the part of the object that I would like to update:
updateObj(person, 'personal.address', {
  state: {
    abbrName: 'OR',
    fullName: 'Oregon',
    capital: 'Salem'
  },
  zip: '97062'
});
This function does it but not with the merging behavior above:
var updateObjectWithStringProp = function(obj, prop, value) {
  if (typeof prop === "string") {
    var prop = prop.split('.');
  }
  if (prop.length > 1) {
    var p = prop.shift();
    if (obj[p] == null || typeof obj[p] !== 'object') {
      obj[p] = {};
    }
    updateObjectWithStringProp(obj[p], prop, value);
  } else {
    obj[prop[0]] = value;
  }
  return obj;
};
How do I edit this function to also include the merging behavior?
 
     
    