我们有两个相同结构的对象,我们希望根据元素名有选择地组合值。有些元素我们希望接受更新值并覆盖,有些元素我们希望忽略更新,还有一些元素是数组,我们希望将它们组合为一个并集。
例如,对于这两个对象…
var server = {
'title': 'string',
'systems': [3,4,5],
'views': 1000,
'authors': ['fred','bill']
};
var update = {
'title': 'new string',
'systems': [5],
'views': 900,
'authors': ['fred','jim']
};
我们要替换title
,替换systems
,忽略views
,并并authors
。生成这个对象:
var result = {
'title': 'new string', // value repaced
'systems': [5], // array wholly replaced
'views': 1000, // update value ignored
'authors': ['fred','bill','jim'] // update unioned with server
};
我们已经尝试了_.merge
和_.assign
,但它们给出了错误的结果(例如systems
变成[5,4,5]
),也没有提供忽略特定元素更新的选项(例如视图)
将来可能会添加更多的元素(在代码的其他地方),所以我们不想自定义代码的组合,而是依赖于默认的_.assign
或_.merge
类行为的未知元素。
是否有一个lodash函数可以处理这个?
我不知道是否可以使用lodash,但这里有一个普通的javascript函数可以帮助你做到这一点:
const server = {
'title': 'string',
'systems': [3,4,5],
'views': 1000,
'authors': ['fred','bill']
};
const update = {
'title': 'new string',
'systems': [5],
'views': 900,
'authors': ['fred','jim']
};
const merge = (source, update, actions) => Object.keys(source).reduce((result, k) => {
if (actions.replace.includes(k)) {
result[k] = update[k];
} else if (actions.ignore.includes(k)) {
result[k] = source[k];
} else if (actions.union.includes(k)) {
result[k] = [...new Set([...source[k], ...update[k]])];
}
return result;
}, {});
console.log(merge(server, update, {replace: ['title', 'systems'], ignore: ['views'], union: ['authors']}));
其中actions
是类型为
{replace: [<properties to replace>], ignore: [<properties to ignore>], union: [<properties to union>]}