У меня есть знак подчеркивания.Как частично обновить вложенный объект, учитывая ключ как строку?
у меня есть:
var person = {
personal: {
fname: 'Victor',
lname: 'Lee',
address: {
street: '1234 Main',
state: {
abbrName: 'CA',
fullName: 'California',
timezone: 'PST'
},
zip: '94043'
}
}
};
Я хотел бы обновить несколько свойств, но оставить нетронутыми другие.
Вместо того, чтобы писать три отдельные линии:
person.personal.address.state.abbrName = 'OR';
person.personal.address.state.fullName = 'Oregon';
person.personal.address.zip = '97062';
Я хочу, чтобы иметь возможность установить весь реквизит в одной строке коды, но и оставить другие свойства нетронутыми.
Если я:
_.extend(person.personal.address, {
state: {
abbrName: 'OR',
fullName: 'Oregon'
},
zip: '97032'
});
Результирующий объект имеет часовой пояс вырубали:
{
personal: {
fname: 'Victor',
lname: 'Lee',
address: {
street: '1234 Main',
state: {
abbrName: 'CA',
fullName: 'California',
},
zip: '94043'
}
}
};
Нечто подобное было бы идеально:
var updateObj = function(obj, key, value){
// stuff
return obj;
};
и бежать, как:
updateObj(person, 'personal.address', {
state: {
abbrName: 'OR',
fullName: 'Oregon'
},
zip: '97032'
});
Пока у меня это есть, но он полностью перезаписывает одно свойство за раз.
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
Хорошо, я думаю, что я близко:
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;
};
Это сливает информацию, даже если ее зажатый между уровнями в объекте:
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);
{
personal: {
fname: 'Victor',
lname: 'Lee',
address: {
street: '1234 Main',
state: {
abbrName: 'OR',
fullName: 'Oregon',
timezone: 'PST',
capital: 'Salem'
},
zip: '97062'
}
}
}
Но, как я уже сказал, я хотел бы предоставить струнный путь к той части объекта, который я хотел бы обновить:
updateObj(person, 'personal.address', {
state: {
abbrName: 'OR',
fullName: 'Oregon',
capital: 'Salem'
},
zip: '97062'
});
Эта функция делает это, но не с поведением слияния выше :
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;
};
Как отредактировать эту функцию, чтобы также включить слияние?
В частном случае, описанном выше, есть причина, почему вы не попробовать '_.extend (person.personal.address, {состояние: 'МО', почтовый индекс: 44444})'? –
Любая причина, по которой вы используете 'Object.prototype.toString.call (obj [e]) ===" [object Object] ", а не' typeof obj [e] == 'object''? – RobG
Используйте функцию mergerecursive из [this] (http://stackoverflow.com/a/383245/502613) вопроса. Это сработает. – Jorg