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?