【问题标题】:Drill down into multi-nested arrays syntactic sugar深入研究多嵌套数组语法糖
【发布时间】:2017-11-02 18:24:25
【问题描述】:

当我需要深入研究数据结构时,我经常发现自己遵循这种模式,尤其是在我的 Redux reducer 中:

state.items = state.items.map((item) => {
  item.subItems = item.subItems.map((subItem) => {
    subItem.bottomItems = subItem.bottomItems.map((bottomItem) => {
      // do something with bottomItem...
      bottomItem.foo = 'bar';
      return bottomItem;
    });
    return subItem;
  });
  return item;
});

这似乎有很多样板要降到bottomItems 级别。

ES6 或 ES7 是否提供了一些语法糖来简化这种模式?

【问题讨论】:

  • 好吧,你可能不想改变状态本身:)。您是更新每个项目的每个子项目的每个底部项目还是更具体的内容?
  • @nem035 我实际上并没有意识到我的突变不是最佳实践...感谢您引起我的注意。是的,我正在尝试更新每个bottomItem
  • 您正在寻找的是 lenses,这是一种用于向下钻取的可组合抽象。虽然它们没有正式标准化或提供任何语法糖,但它们需要在用户空间中实现。

标签: javascript ecmascript-6 redux syntactic-sugar ecmascript-2016


【解决方案1】:

首先我要提到的是,您那里的代码会修改原始状态。为了维护 redux 的state immutability principle,您只想返回新对象,而不是一路修改现有对象。

就更简单的语法而言,如果您使用arrow functionsobject spread,这种模式还不错:

return {
  items: state.items.map(item => ({
    ...item,
    subItems: item.subItems.map(subItem => ({
      ...subItem,
      bottomItems: subItem.bottomItems.map(bottomItem => ({
        ...bottomItem,
        foo: 'bar' // update foo to 'bar' for every bottomItem in every subItem in every item
      })
    })
  })
}

请注意,对象传播还不是语言的一部分,它目前是第 3 阶段的提案,很可能会成为下一个 ECMAScript 版本的一部分。因此,您必须使用诸如 Babel 之类的东西对其进行转译,以便在当今的浏览器中工作。

如果您不希望这样做,并且希望今天本地可用的功能,您可以改用Object.assign

return {
  items: state.items.map(item => Object.assign({}, item, {
    subItems: item.subItems.map(subItem => Object.assign({}, subItem, {
      bottomItems: subItem.bottomItems.map(bottomItem => Object.assign({}, bottomItem, {
        foo: 'bar' // update foo to 'bar' for every bottomItem in every subItem in every item
      })
    })
  })
}

由于您似乎想要一个更清晰、更易读的语法,我建议选项 1 :)

【讨论】:

  • 虽然 OP 要求 ES6/ES7 解决方案
  • @nem035 是第一个缺少一些括号的代码示例吗?例如,最后一个结束括号似乎与 subItem => 之后的开始括号对齐
  • 这是故意的。如果你有一个返回对象的箭头函数,简短的语法是这样的() => ({ /* object props */ }),而不是更冗长的() => { return { /* object props */ } }
【解决方案2】:

是的,嵌套的不可变更新可能会很痛苦(正如我在 Redux 文档的 Structuring Reducers - Immutable Update Patterns 部分中提到的那样)。

您可能想考虑使用众多不可变更新实用程序库之一。这些库提供了多种语法和抽象来进行更简单的嵌套不可变更新。有些使用字符串键路径,有些使用嵌套对象定义。一个典型的例子可能是someLib.set(["items", "subItems", "bottomItems", 0, "someField"], someValue)

请参阅我的Redux addons catalogImmutable Data#Immutable Update Utilities 部分以获取可用库的列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-07
    • 1970-01-01
    • 1970-01-01
    • 2020-01-10
    • 1970-01-01
    • 2016-02-10
    • 2015-12-29
    相关资源
    最近更新 更多