javascript - 对象与数组:在状态中存储对象集合时是否有明显的赢家?
问题描述
在状态管理 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)
我在这里有什么遗漏吗?两者的可用性是否取决于数据集的大小,或者可能取决于使用“查找”操作的频率?只是试图确定哪些情况可能决定其中一种或另一种的优越性。
解决方案
没有一个真正的答案,唯一有效的答案是It取决于TM。
尽管有不同的用例需要不同的解决方案。这一切都归结为如何使用数据。
单个对象数组
最好在顺序很重要并且可能呈现为整个列表时使用,其中每个项目都直接从列表循环传递并且很少单独访问项目。
这是存储接收到的数据的最快(最少的开发人员时间消耗)方式,如果数据已经开始使用这种结构,这通常是这种情况。
数组状态的优点
- 可以轻松跟踪物品订单,
- 轻松循环,其中单个项目从列表中向下传递。
- 它通常是从 API 端点返回的原始结构,
数组状态的缺点
- 更新项目将触发完整列表的呈现。
- 需要更多代码来查找/编辑单个项目。
按 id 的单个对象
最好在顺序无关紧要时使用,它主要用于呈现单个项目,例如在编辑项目页面上。这是朝着标准化状态方向迈出的一步,将在下一节中解释。
对象状态的优点
- 通过 ID 快速轻松地访问/更新
对象状态的缺点
- 无法轻松重新订购商品
- 循环需要一个额外的步骤(例如
Object.keys().map
) - 更新项目将触发完整列表的呈现,
- 可能需要解析成目标状态对象结构
标准化状态
通过 id 使用所有项目的对象和所有 id 字符串的数组来实现。
{
items: {
byId: { /**/ },
allIds: ['abc123', 'zxy456', /* etc. */],
}
}
这在以下情况下变得必要:
- 所有用例的可能性均等,
- 性能是一个问题(例如巨大的列表),
- 数据嵌套很多和/或在不同级别重复,
- 将列表重新渲染为不良副作用
不良副作用的一个示例:更新会触发完整列表重新呈现的项目可能会丢失模式打开/关闭状态。
优点
- 可以跟踪项目订单,
- 引用单个项目很快,
- 更新项目:
- 需要最少的代码
- 由于完整列表循环遍历
allIds
字符串,因此不会触发完整列表渲染,
- 更改顺序快速而清晰,渲染最少,
- 添加项目很简单,但需要在两个数据集中都添加它
- 避免嵌套数据结构中的重复对象
缺点
- 个人移除是最糟糕的情况,虽然也不是什么大不了的事。
- 需要更多代码来管理整体状态。
- 保持两个状态数据集同步可能会令人困惑。
这种方法是在很多地方使用的常见规范化过程,这里有额外的参考资料:
- Redux 的状态规范化是强烈推荐的最佳实践,
- normalizr库。_
推荐阅读
- css - CSS 悬停不工作字体真棒。为什么?
- jquery - 如何路由到我视图的子文件夹中的图像
- python - 如何用python生成恒等张量?
- javascript - 容器内的“延迟加载”图像添加了“显示:无”?
- spring - 如何在春季使用 oauth2 中的刷新令牌更新访问令牌?
- r - pchisq 命令正确但答案错误
- visual-studio - 使本地项目项可从 VS C++ 2017 中的共享项目访问
- android - Google 登录失败,Api 异常 12500
- coffeescript - 如何在 Coffeelint 中禁用“类名应为 UpperCamelCased”警告?
- ruby-on-rails - Rails 5嵌套表单更新不创建新记录