首页 > 解决方案 > 对象与数组:在状态中存储对象集合时是否有明显的赢家?

问题描述

在状态管理 javascript 框架(例如:React)中,如果您有一组对象要存储在状态中,那么保存它们的更有用和/或性能更好的数据集类型是对象还是数组?以下是我能想到的在 state 中使用它们时可能会出现的一些差异:

引用条目: 对于对象,您可以通过其键直接引用条目,而对于数组,您必须使用类似dataset.find(). 在对小数据集进行单次查找时,性能差异可能可以忽略不计,但我想如果 find 函数必须在一个大数据集上进行细化,或者如果您需要一次引用许多条目,它会变得更大。

更新数据集: 使用对象,您可以使用 来添加新条目{...dataset, [newId]: newEntry}、使用 编辑旧条目,{...dataset, [id]: alteredEntry}甚至可以使用 来编辑多个条目{...dataset, [id1]: alteredEntry1, [id2]: alteredEntry2}。而对于数组,添加很容易[...dataset, newEntry1, newEntry2],但要进行编辑,您必须使用find(),然后可能会编写几行代码来克隆数据集和/或为了不变性的条目。然后对于编辑多个条目,它要么需要一个find()函数循环(这对于大型列表来说听起来很糟糕),要么使用filter()然后必须处理将它们添加回数据集中。

删除 要从对象数据集中删除单个条目,delete dataset[id]您可以使用循环或 lodash 函数(如_.omit(). 要从数组中删除条目(并保持密集),您必须使用findIndex()and then .slice(index, 1),或者只使用filter()which 可以很好地用于单个或多个删除。我不确定这些选项中的任何一个对性能的影响。

循环/渲染:对于一个数组,您可以使用或dataset.map()轻松渲染一个专门的集合。对于要在 React 中渲染的对象,您必须在对其运行其他迭代函数之一之前使用它,我认为这可能会根据数据集大小造成性能损失。dataset.filter()dataset.sort()Object.values(dataset)

我在这里有什么遗漏吗?两者的可用性是否取决于数据集的大小,或者可能取决于使用“查找”操作的频率?只是试图确定哪些情况可能决定其中一种或另一种的优越性。

标签: javascriptarraysreactjsperformanceobject

解决方案


没有一个真正的答案,唯一有效的答案是It取决于TM

尽管有不同的用例需要不同的解决方案。这一切都归结为如何使用数据。

单个对象数组

最好在顺序很重要并且可能呈现为整个列表时使用,其中每个项目都直接从列表循环传递并且很少单独访问项目。

这是存储接收到的数据的最快(最少的开发人员时间消耗)方式,如果数据已经开始使用这种结构,这通常是这种情况

数组状态的优点

  • 可以轻松跟踪物品订单,
  • 轻松循环,其中单个项目从列表中向下传递。
  • 它通常是从 API 端点返回的原始结构,

数组状态的缺点

  • 更新项目将触发完整列表的呈现。
  • 需要更多代码来查找/编辑单个项目。

按 id 的单个对象

最好在顺序无关紧要时使用,它主要用于呈现单个项目,例如在编辑项目页面上。这是朝着标准化状态方向迈出的一步,将在下一节中解释。

对象状态的优点

  • 通过 ID 快速轻松地访问/更新

对象状态的缺点

  • 无法轻松重新订购商品
  • 循环需要一个额外的步骤(例如Object.keys().map
  • 更新项目将触发完整列表的呈现,
  • 可能需要解析成目标状态对象结构

标准化状态

通过 id 使用所有项目的对象和所有 id 字符串的数组来实现。

{
  items: {
    byId: { /**/ },
    allIds: ['abc123', 'zxy456', /* etc. */],
  }
}

这在以下情况下变得必要:

  • 所有用例的可能性均等,
  • 性能是一个问题(例如巨大的列表),
  • 数据嵌套很多和/或在不同级别重复,
  • 将列表重新渲染为不良副作用

不良副作用的一个示例:更新会触发完整列表重新呈现的项目可能会丢失模式打开/关闭状态。

优点

  • 可以跟踪项目订单,
  • 引用单个项目很快,
  • 更新项目:
    • 需要最少的代码
    • 由于完整列表循环遍历allIds字符串,因此不会触发完整列表渲染,
  • 更改顺序快速而清晰,渲染最少,
  • 添加项目很简单,但需要在两个数据集中都添加它
  • 避免嵌套数据结构中的重复对象

缺点

  • 个人移除是最糟糕的情况,虽然也不是什么大不了的事。
  • 需要更多代码来管理整体状态。
  • 保持两个状态数据集同步可能会令人困惑。

这种方法是在很多地方使用的常见规范化过程,这里有额外的参考资料:


推荐阅读