我有下划线。
我有:
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;
};
如何编辑此功能以包含合并行为?
答案 0 :(得分:0)
您可以使用递归,但请记住,它可能会出现具有高嵌套的大对象的问题。
注意:在进行此类功能之前,您应该考虑一些事情
undefined
还是newValues
?也可以有其他参数。
function mergeObject(source, newValue, allowNewProps) {
if (typeof newValue === "object" && typeof source === "object") {
for (var k in newValue) {
if (Array.isArray(newValue[k]) && Array.isArray(source[k])) {
for (var i = 0; i < newValue[k].length; i++) {
mergeObject(source[k][i], newValue[k][i]);
}
}
if (typeof newValue[k] === "object") {
mergeObject(source[k], newValue[k]);
} else if (source[k] !== undefined || allowNewProps) {
source[k] = newValue[k];
}
}
}
}
答案 1 :(得分:-1)
是否可以将库从下划线更改为lodash?
然后您将拥有相同(以及更多)可用的功能,包括_.defaultsDeep
。
您可以在一行中执行合并,在中间保留您的时区。
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"
}
}