一文详解JavaScript中使用对象数组、对象(字典)保存数据的区别

 更新时间:2026年03月12日 15:12:49   作者:Never_Satisfied  
这篇文章将深入对比了JavaScript中存储产品数据的两种方式,分别是数组和对象(字典),文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下

示例:

 const products=[
	 {id:'aaa',name:'aname',overview:'aoverview'},
	 {id:'bbb',name:'bname',overview:'boverview'}
 ];
 const products={
	 'aaa':{name:'aname',overview:'aoverview'},
	 'bbb':{name:'bname',overview:'boverview'}
 };

在 JavaScript 中存储产品数据,你给出的两种方案分别使用了数组对象(字典)。下面从多个角度分析它们的优劣、运行效率以及底层机制,以便你根据实际需求做出选择。

1. 数据结构概览

// 方案一:数组
const productsArray = [
  { id: 'aaa', name: 'aname', overview: 'aoverview' },
  { id: 'bbb', name: 'bname', overview: 'boverview' }
];

// 方案二:对象(以 id 为键)
const productsObject = {
  'aaa': { name: 'aname', overview: 'aoverview' },
  'bbb': { name: 'bname', overview: 'boverview' }
};

2. 核心操作对比

操作数组(productsArray)对象(productsObject)
通过 id 查找需要遍历数组,时间复杂度 O(n)
arr.find(p => p.id === id)
直接通过键访问,时间复杂度 O(1)
obj[id]
遍历所有产品直接使用 for、forEach 或 map,内存连续,速度快需先获取 Object.values(obj) 或 Object.keys(obj),产生临时数组,稍慢
添加新产品push 在末尾追加,O(1)(无需移动元素)直接赋值 obj[newId] = {...},O(1)(哈希表插入)
删除产品若需保持顺序,用 splice 会移动后续元素,O(n)
若不关心顺序,可标记删除
使用 delete obj[id],O(1),但可能导致对象进入“慢模式”
更新产品先查找(O(n))再修改,或直接通过已知索引修改(O(1))直接通过键修改 obj[id].name = 'new',O(1)
按 id 排序/筛选可直接用数组方法(sort, filter),方便灵活需先转为数组,再操作

3. 内存占用

  • 数组:每个元素都是一个对象,且内部必须显式存储 id 字段。如果有 N 个产品,就会存储 N 个 id 字符串。
  • 对象:id 作为键(key)存储,值对象中不再需要 id 字段。因此节省了 N 个 id 字符串的内存(但键本身也占用内存,通常比字符串值稍少,因为键被内部化)。

总体而言,对象方案在内存上略优,尤其当数据量较大时差异更明显。

4. JavaScript 引擎内部运作方式

数组(以 V8 引擎为例)

  • 如果数组元素类型一致(例如都是对象),V8 会使用 PACKED_ELEMENTS 模式,元素在内存中连续存储,访问和迭代非常快,CPU 缓存利用率高。
  • 当数组长度变化(如 splice 删除中间元素),需要移动后续元素,开销较大。
  • 引擎还会根据元素类型优化(如数字数组会用 C 语言级别的数组存储),但这里存储的是对象引用,所以仍是引用数组。

对象(字典)

V8 中对象有两种表示模式:

  • 快速属性:当对象属性数量较少、且属性名是确定的字符串时,V8 会使用隐藏类(Hidden Class)和内联缓存(Inline Cache),属性访问接近 C 语言结构体的速度。
  • 慢速属性(字典模式):当属性被频繁动态添加/删除,或数量很多时,V8 会将对象切换为哈希表实现,此时访问速度仍然 O(1),但常数因子较大,且内存占用增加。

你的 productsObject 键是动态的(每个产品 id 都可能不同),且数量可能较多,很可能最终以哈希表形式存储。但通过 id 访问依然非常快。

5. 实际使用中的优劣总结

方案一:数组

优点

  • 保持顺序(按插入顺序或排序后顺序),适合列表展示。
  • 遍历方便,可直接用数组迭代方法。
  • 与 React/Vue 等框架的列表渲染完美配合(通常需要传递数组)。

缺点

  • 通过 id 查找效率低(需要遍历或额外建立索引)。
  • 删除中间元素成本高(splice 移动元素)。

方案二:对象

优点

  • 通过 id 查找、更新、删除极快(O(1))。
  • 内存稍省(无需重复存 id)。
  • 天然保证 id 唯一性(键不能重复)。

缺点

  • 没有顺序保证(ES6 之后对象键按创建顺序枚举,但删除再添加可能影响顺序)。
  • 遍历需要先转换(Object.values),且转换结果是一个新数组,频繁遍历可能产生临时对象开销。
  • 不能直接使用数组方法(如 map, filter)。

6. 常见优化实践

在实际开发中,经常需要兼顾快速查找顺序遍历。这时可以采用复合结构

const productsList = [];                // 用于顺序展示
const productsMap = {};                 // 用于快速查找

// 添加产品
function addProduct(product) {
  productsList.push(product);
  productsMap[product.id] = product;
}

// 通过 id 查找
function getProduct(id) {
  return productsMap[id];
}

// 删除产品(假设不关心顺序,用 filter 重建列表)
function deleteProduct(id) {
  productsList = productsList.filter(p => p.id !== id);
  delete productsMap[id];
}

这种方式结合了两者的优点,但需要维护两个结构的一致性。

7. 如何选择

如果你的应用主要场景是:

  • 根据 id 频繁查找、更新(如购物车、商品详情页) → 选对象
  • 展示产品列表、排序、过滤(如后台管理列表) → 选数组
  • 两者都很重要 → 考虑复合结构

数据量大小:如果数据量很小(几十条),两种方案性能差异可以忽略,选你写起来更方便的即可。

是否需要保持顺序:如果需要按特定顺序展示(如按添加时间),数组更合适;如果顺序不重要,对象也能满足。

8. 内部机制延伸理解

数组查找为什么慢?因为数组本身没有建立 id 到索引的映射,每次查找都必须遍历所有元素,直到找到匹配的 id。如果数组很大,这个开销会线性增长。

对象键访问为什么快?对象在内存中通过哈希函数将键映射到存储位置,平均只需一次计算就能定位到值,无论对象中有多少属性(理想情况下)。

delete 操作的影响delete obj[key] 会在对象中留下一个“空洞”,如果对象之前处于快速模式,可能会触发引擎将其降级为慢速字典模式,后续属性访问性能下降。因此,如果频繁删除并重新添加大量属性,建议用 undefined 标记或改用 MapMap 专门为频繁增删设计,性能更好)。

总结

两种方案各有优劣,没有绝对的好坏。理解它们的底层行为后,你可以根据业务场景的读写比例是否强调顺序数据量级来灵活选择。在大多数中大型应用中,对象(或 Map)用于快速查找,数组用于列表渲染是常见模式。

到此这篇关于一文详解JavaScript中使用对象数组、对象(字典)保存数据的区别的文章就介绍到这了,更多相关JavaScript存储数据方法对比内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 多种js图片预加载实现方式分享

    多种js图片预加载实现方式分享

    这篇文章主要为大家详细介绍了多种js图片预加载实现方式,包括html标签或css加载图片、纯js实现预加载,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • js实现动态加载数据瀑布流

    js实现动态加载数据瀑布流

    这篇文章主要为大家详细介绍了js实现动态加载数据瀑布流,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • IE6 hack for js 集锦

    IE6 hack for js 集锦

    本文主要讲诉了使用js实现网站功能兼容IE6,非常的实用的小技巧,有需要的朋友可以参考下
    2014-09-09
  • JavaScript 继承的实现

    JavaScript 继承的实现

    正因为JavaScript本身没有完整的类和继承的实现,并且我们也看到通过手工实现的方式存在很多问题, 因此对于这个富有挑战性的任务网上已经有很多实现了
    2009-07-07
  • 请求时token过期自动刷新token操作

    请求时token过期自动刷新token操作

    这篇文章主要介绍了请求时token过期自动刷新token操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Javascript highcharts 饼图显示数量和百分比实例代码

    Javascript highcharts 饼图显示数量和百分比实例代码

    这篇文章主要介绍了Javascript highcharts 饼图显示数量和百分比实例代码的相关资料,这里附有实例代码,需要的朋友可以参考下
    2016-12-12
  • layui 实现table翻页滚动条位置保持不变的例子

    layui 实现table翻页滚动条位置保持不变的例子

    今天小编就为大家分享一篇layui 实现table翻页滚动条位置保持不变的例子,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-09-09
  • JavaScript实现图片懒加载的两种方式

    JavaScript实现图片懒加载的两种方式

    现在的科技发达,图片的资源占比越来越大,对图片在页面的优化已经成为前端开发必备的技术之一,难的图片懒加载方法咱们看着头大,简单,易懂的才适合我们程序员,所以本文给大家介绍了JavaScript实现图片懒加载的两种方式,需要的朋友可以参考下
    2024-04-04
  • 移动端web滚动分页的实现方法

    移动端web滚动分页的实现方法

    这篇文章主要为大家详细介绍了移动端web滚动分页的实现方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • js图片延迟技术一般的思路与示例

    js图片延迟技术一般的思路与示例

    现将img元素对应的src路径设置为背景图片,而该img所对应的url路径存放在一个自设的属性中
    2014-03-03

最新评论