【问题标题】:Create a pure function to merge objects创建一个纯函数来合并对象
【发布时间】:2019-02-07 00:04:08
【问题描述】:

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

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'}}

我可以使用其余参数,但我不知道如何追加而不是覆盖。我不能只循环属性,因为我希望函数是纯的(redux reducer)。

有人有什么想法吗?

【问题讨论】:

  • 对于任何值得通用 ES6 模式的东西,您都会看到 this.setState({...this.state, ...updates}) 其中更新是任何更改。这实际上只是语法糖,基本上是 Object.assign,但在我看来它有助于清晰。看看 redux 教程。你问的基本上是redux的本质。 redux.js.org/api/store。至于你的函数问题:纯函数只是意味着输出总是与相同的输入相同,并且输入没有改变或-> Object.assign({}, oldObj, newObj)
  • @DanielB.Chapman 奇怪的是,当我使用 rest/spread 语法并覆盖原始对象的值时,所以当我在上面的示例中使用 rest 时,它缺少描述。跨度>
  • "函数会返回:{ ... }" - 为什么description 没有出现在预期的输出中?

标签: javascript reactjs redux functional-programming


【解决方案1】:

您可以使用spread syntax:

ECMAScript 提案(第 4 阶段)的 Rest/Spread 属性将扩展属性添加到对象字面量。它将自己的可枚举属性从提供的对象复制到新对象。

...或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 级。如果您希望进行 deep 合并,我建议您查看this answer

  • 在撰写本文时,Object.assign 具有比对象字面量上的扩展语法更好的跨浏览器支持,如您所见 here。如果您正确使用Babel 或任何其他转译器,这应该不是问题,但值得一提。

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

【讨论】:

  • 酷,谢谢!只是出于好奇,有没有办法只使用 ES6 rest/spread 语法来做到这一点?
  • @Eitan Yup,在我的 sn-p 中添加了一个示例。
  • 这就是我认为它会起作用的方式。我试过了,它覆盖了描述,但也许我有错字。谢谢!
  • "... 带有属性(和子属性)" - 这是一个浅合并
  • @user633183 在附注中添加了该信息。事实上,你的评论让我想到了这个stackoverflow.com/questions/27936772/…。这个问题更像是这个问题的重复,所以我会这样标记它。
【解决方案2】:

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 指出的那样,要创建一个新对象,您应该在开头添加 {}。

【讨论】:

  • 哎呀,你刚刚以这种方式变异了state。添加一个额外的空{} 作为Object.assign 的第一个参数以避免这种情况,如下所示:Object.assign({}, state, newState)
  • @NicholasKyriakides Op 想改变我认为的状态
  • 我认为声明 I would like to create a pure function... 另有说明。
  • 这个returns 'state' updated 哈哈。我不知道,无论哪种方式 op 现在都知道。
  • 我认为这只是 OP 的混乱,因为这两个陈述都是矛盾的,但我可能是错的。
猜你喜欢
  • 2021-03-28
  • 2022-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-26
相关资源
最近更新 更多