Javascript 如果键是字符串,如何部分更新嵌套对象?
我有下划线 我有:Javascript 如果键是字符串,如何部分更新嵌套对象?,javascript,underscore.js,Javascript,Underscore.js,我有下划线 我有: var person = { personal: { fname: 'Victor', lname: 'Lee', address: { street: '1234 Main', state: { abbrName: 'CA', fullName: 'California', timezone: 'PST' }, zip: '94043' }
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;
};
编辑
好吧,我想我已经接近了:
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;
};
如何编辑此函数以同时包含合并行为?是否可以将库从下划线更改为 然后,您将拥有相同(以及更多)的可用功能,包括
\uuu.defaultsDeep
您可以在1行中执行合并,在中间保留您的时区。
var person = {
personal: {
fname: 'Victor',
lname: 'Lee',
address: {
street: '1234 Main',
state: {
abbrName: 'CA',
fullName: 'California',
timezone: 'PST'
},
zip: '94043'
}
}
};
var update = {
personal: {
address: {
state: {
abbrName: 'OR',
fullName: 'Oregon'
},
zip: '97032'
}
}
}
var result = _.defaultsDeep(update, person);
结果将决定:
result = {
"personal":{
"address":{
"state":{
"abbrName":"OR",
"fullName":"Oregon",
"timezone":"PST"
},
"zip":"97032",
"street":"1234 Main"
},
"fname":"Victor",
"lname":"Lee"
}
}
您可以使用递归,但请记住,它可能会遇到具有高嵌套的大型对象的问题 注意:在做这样的函数之前,你应该考虑一些事情。
- 这两个值都可以是简单对象
- 这两个值都可以是对象的数组
- 这两个值都可以是数组
- 新对象可以有额外的参数。是否允许向原始对象添加值
- 源对象可以为空吗?如果是,您应该返回
还是未定义的
新值
函数mergeObject(源、newValue、allowNewProps){
if(typeof newValue==“object”&&typeof source==“object”){
for(新值中的var k){
if(Array.isArray(newValue[k])&&Array.isArray(source[k])){
对于(var i=0;i
在上面概述的特定情况下,您是否有理由不尝试.extend(person.personal.address,{state:'MO',zip:44444})
?您使用Object.prototype.toString.call(obj[e])====“[Object Object]”而不是obj[e]的类型==“object”
?使用问题中的mergerecursive函数。好的,我已经编辑了原始问题。最大的问题是更新夹在对象两个级别之间的信息。@Jorg这是一个非常普通的答案。try..catch完全没有必要,而且obj2[p]。构造函数==Object
在许多情况下都会失败。