创建一个纯函数来合并对象

Eit*_*tan 3 javascript functional-programming reactjs redux

假设我有变量'state'和'newState'.我想创建一个纯函数,返回使用'newState'的属性(和子属性)更新的'state'.这是一个例子:

const state = {id:1, name:'aName', description: 'aDescription'};

const newState = {id:1, name:'newName', subItems: {id:3, type:'whatever'}};
Run Code Online (Sandbox Code Playgroud)

该函数将返回:

{id:1, name:'newName', subItems: {id:3, type:'whatever'}}
Run Code Online (Sandbox Code Playgroud)

我可以使用rest参数,但我不知道如何追加而不是覆盖.我不能只是遍历属性,因为我希望函数是纯的(redux reducer).

有人有主意吗?

Nik*_*des 6

您可以使用扩展语法:

ECMAScript提议的Rest/Spread属性(阶段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);
Run Code Online (Sandbox Code Playgroud)

附注:

  • 扩展@ user633183的注释,两种方式都会产生浅层合并.他们只有1级深度.如果你想进行深度合并,我建议你查看这个答案.

  • 在撰写本文时,Object.assign有更好的跨浏览器支持,而不是在对象文字上传播语法,正如您在此处所见.如果您正确使用Babel或任何其他转换器,这应该不是问题,值得一提.

  • 我们通常不会将函数称为不可变的(实际上它们可能是因为它们本身就是值,但这可能不是您在问题的上下文中的意思).值可以是不可变的,函数可以是纯的 ; 这意味着它们不会引起副作用,例如改变他们的论点.