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

问题描述 投票:3回答:2

假设我有变量'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)。

有人有主意吗?

javascript reactjs redux functional-programming
2个回答
6
投票

你可以使用spread syntax

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);

附注:

  • 扩展@ user633183的注释,两种方式都会产生浅层合并。他们只有1级深度。如果你想进行深度合并,我建议你查看this answer
  • 在撰写本文时,Object.assign具有更好的跨浏览器支持,而不是在对象文字上传播语法,正如您可以看到here。虽然如果你正确使用Babel或任何其他的转换器,这应该不是问题,值得一提。
  • 我们通常不会将函数称为不可变的(实际上它们可能是因为它们本身就是值,但这可能不是您在问题的上下文中的意思)。值可以是不可变的,函数可以是纯的;这意味着它们不会引起副作用,例如改变他们的论点。

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)

正如Nicholas Kyriakides指出的那样,要创建一个新对象,您应该在开头添加{}。

© www.soinside.com 2019 - 2024. All rights reserved.