比方说,我有变量'state'和'newState'。我想创建一个纯函数,该函数返回用“ newState”的属性(和子属性)更新的“ state”。这是一个示例:
const state = {id:1, name:'aName', description: 'aDescription'};
const newState = {id:1, name:'newName', subItems: {id:3, type:'whatever'}};
该函数将返回:
{id:1, name:'newName', subItems: {id:3, type:'whatever'}}
我可以使用rest参数,但是我不知道如何添加而不是覆盖。我不能只遍历属性,因为我希望函数是纯函数(redux reducer)。
有人有什么想法吗?
答案 0 :(得分:6)
您可以使用spread syntax:
ECMAScript建议的“休息/扩展属性”(阶段4)将扩展属性添加到对象文字中。它将自己的可枚举属性从提供的对象复制到新对象。
...或Object.assign
,第一个参数是一个空对象:
Object.assign()方法用于将所有可枚举的自身属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
const state = {id:1, name:'aName', description: 'aDescription'};
const newState = {id:1, name:'newName', subItems: {id:3, type:'whatever'}};
// Example with spread syntax:
const result1 = { ...state, ...newState };
// Example with Object.assign:
// @NOTE: Providing an empty `{}` as the 1st argument,
// ensures you don't mutate `state`.
const result2 = Object.assign({}, state, newState);
console.log(result1);
console.log(result2);
扩展@ user633183的注释,两种方式都会产生 shallow 合并。他们只有1级深度。如果您想进行深合并,建议您查看this answer。
在撰写本文时,Object.assign
具有比跨对象文字扩展语法更好的跨浏览器支持,如您所见here。如果正确使用Babel或任何其他编译器,这应该不成问题,但值得一提。
我们通常不将函数称为不变的(实际上它们可以是函数,因为它们本身就是值,但这在问题中可能并不是您要表达的意思)。值可以是不可变,函数可以是 pure ;意味着它们不会引起副作用(例如,改变其参数)。
答案 1 :(得分:3)
Object.assign
对于更新state
可能有用:
const state = {id:1, name:'aName', description: 'aDescription'};
const newState = {id:1, name:'newName', subItems: {id:3, type:'whatever'}};
Object.assign(state,newState)//<-- updates state
console.log(state)
正如NicholasKyriakides指出的那样,要创建一个新对象,应在开头添加{}。