迭代 JavaScript Map

2025年4月18日 | 阅读 8 分钟

键值对存储在 JavaScript 中称为 Map 对象的信息结构中。与键的字符串类型有限制的普通对象相比,Map 可以使用任何类型的键,包括字符串、对象、函数等。在某些情况下,这使其成为更具适应性和灵活性的数据结构。

为了处理这些键值对,Map 对象具有一些属性和方法。遍历 Map 是开发人员经常需要完成的最基本任务之一。本文将探讨 JavaScript 中 Map 的各种迭代方法、Map 与普通对象之间的区别以及每种方法的推荐实践。

使用此方法,您可以为 Map 中的每个键值对运行一个特定的函数。

1. 使用 forEach() 方法

forEach() 方法接受的 callback 函数的两个参数是值和键。

它会按照键值对插入的顺序遍历 Map。

此方法简单实用,尤其是在您希望对每个 Map 访问执行特定操作时。但如果您需要条件退出,它的灵活性不如其他方法,因为它不提供提前终止循环的机制。

2. 使用 for...of 循环

遍历 Map 的另一种流行且灵活的方法是 for...Of 循环。Map 对象直接用于 for...Of 循环,因为它实现了可迭代协议。

默认情况下,for...Of 循环将遍历键值对作为数组。

说明

通过使用 for...Of 循环以数组的形式检索 Map 中的每个键值对,您可以使用数组解构同时访问键和值。

for...Of 循环是最强大的技术之一,因为它允许通过 break 语句提前终止循环,而 forEach() 不允许这样做。

3. 使用 map.keys() 遍历键

如果您只对 Map 中包含的键感兴趣,可以使用 keys() 方法。此方法返回的迭代器包含 Map 中每个元素的键。

说明

  • map.Keys() 返回 Map 的键的迭代器。
  • 然后,您可以使用 for...Of 循环遍历这些键。
  • 当您只对键感兴趣而不需要相应的值时,此方法会很有用。

4. 使用 map.values() 遍历值

同样,如果您只对 Map 的值感兴趣,可以使用 values() 方法。此方法返回一个迭代器,其中包含 Map 中每个元素的对应值。

说明

  • map.Values() 返回 Map 的值的迭代器。
  • 与 keys() 类似,您可以使用 for...Of 循环遍历值。
  • 当您主要对值而不是键感兴趣时,此方法是最佳选择。

5. 使用 map.entries() 遍历条目

entries() 方法返回一个迭代器,其中包含 Map 中每个元素的 [key, value] 数组。虽然它与 for...Of 的默认行为相对应,但有时您可能更喜欢这种特定方法。

  • 原因是 map.Entries() 返回 [key, value] 对的迭代器。
  • 此方法与直接在 Map 上使用 for...Of 基本相同,并且可以应用于任何技术结构。

6. 将 Map 转换为数组以进行迭代

即使 Map 的内置迭代函数非常强大,但在某些情况下,您可能需要将 Map 转换为数组以便进一步对其进行处理。如果您需要使用 map()、filter() 或 reduce() 等数组方法,这会很有用。

通过将 Map 或其键/值转换为数组,Array.From() 允许您使用所有数组功能。

  • 当您需要对 Map 的数据执行复杂的操作或修改时,这非常有用。
  • 比较和重复项迭代
  • Map (new Map()) 和 JavaScript 对象 () 由于能够存储键值对而经常进行比较。但存在一些区别:

键类型: Map 支持任何类型的键,包括函数、对象和数字,而对象只支持字符串和符号。

顺序: 虽然对象键的顺序可能因 JavaScript 引擎而异,但 Map 会保留其元素的插入顺序。

大小: 虽然对象的大小需要使用 Object.Keys(obj).Length 手动确定,但 Map 提供了一个 size 属性,可立即返回键值对的数量。

迭代: 与通常需要 for...in 或 Object.Entries() 实现类似功能的对象不同,Map 具有更灵活、更强大的迭代方法。

优点

1. 灵活的键类型

Map 可以使用任何类型的键是其相对于普通对象的最大优势之一。JavaScript 对象需要其键为字符串或符号,但 Map 允许键为任何数据类型。

  • 数字
  • 布尔值
  • 对象
  • 函数
  • 数组

由于其灵活性,开发人员可以存储简单对象无法处理的复杂键值对。这在迭代此类 Map 时特别有用,因为 Map 非常适合需要高级键处理的用例,因为迭代方法(forEach()、for...Of、map.Keys()、map.Entries() 等)直接提供对非字符串键的访问。

由于其灵活性,Map 在处理非标准键时具有优势,并允许开发人员轻松地迭代这些复杂结构。

2. 维护插入顺序

Map 中的键值对按照插入时的顺序进行迭代。此功能提供了一个可靠且可预测的迭代顺序,而 JavaScript 对象通常不保证这一点。虽然现代 JavaScript 引擎通常会保留对象属性的顺序,但与 Map 不同,它不是对象默认的功能。

当键顺序很重要时,例如在以下情况下,Map 的插入顺序保留尤其有用:

按特定顺序显示数据:在列表中或网站上显示数据时,维护键值对的顺序可能至关重要。

时间敏感数据存储:通过维护插入顺序,可以确保在应用程序中随时间收集数据的数据完整性

3. 内置迭代方法

Map 对象中的多种内置方法使迭代变得简单高效。这些方法包括:

map.forEach():为每个键值对执行一个回调函数。

map.keys():返回键的迭代器。

map.values():返回值迭代器。

map.entries():返回 [key, value] 对的迭代器。

Map.ForEach():为每个键值对运行一个回调函数。

由于这些内置、通用且高效的方法,开发人员无需额外的应用程序功能即可以多种方式迭代 Map 的键、值或两者。此外,Map 对象可以直接在 for...Of 循环中使用,提供了一种简单而有效的方法来迭代条目。

4. 使用数组解构实现更简洁的代码

在迭代 Map 的过程中,能够使用数组解构以便于访问键和值,这是 Map 的一个未被充分认识但非常有益的优势。由于在使用 for...Of 循环时,Map 对象会以数组 ([key, value]) 的形式返回,因此您可以在循环中直接解构它们,从而简化代码并提高其清晰度。

通过消除繁琐的语法(例如访问 key[0] 和 key[1]),数组解构使代码更具可读性,并使作者能够专注于他们的逻辑,而不是技术机制。

5. 优化性能

Map 对象的设计宗旨是尽可能高效地插入、检索和迭代键值对。与普通对象(其中键查找操作可能需要导航对象的原型链或处理与属性相关的开销)不同,Map 从头开始构建,以实现高效的键值对管理。

当存在大量键值对或数据结构频繁更新时,这种速度提升变得至关重要。在某些情况下,特别是当键不是字符串时,Map 比普通对象更快,因为它们对键查找具有 O(1) 的时间复杂度。

Map 的性能优势在涉及大量数据检索或操作的用例中显而易见,尤其是在与有效管理大型数据集的技术结合使用时。

6. 避免键冲突

JavaScript 对象将键转换为字符串可能会导致键冲突或无意的属性覆盖。例如,将不同的对象作为键添加到普通对象中可能无法按预期工作,因为两个键都可能被强制转换为字符串,例如 [object Object]。

Map 通过允许非字符串键和使用严格的键相等性来避免此问题。因此,即使两个对象具有相同的字符串表示形式,它们也可以在 Map 中作为不同的键存在。

在此示例中,由于 obj1 和 obj2 被视为不同的键,因此 Map 的完整性得到了维护。当应用程序使用复杂的数据结构或对象作为键时,此优势变得尤为重要。

结论

在处理键值对时,JavaScript 中迭代 Map 提供了一些使其成为比普通对象更强大、更灵活的选择的优势。内置的迭代机制、保持插入顺序以及使用任何数据类型作为键提供了灵活性和可用性。Map 还提供强大的大小计算、防止键冲突,并且经过性能优化,尤其适用于大规模应用程序。

由于这些优势,Map 在需要高效可靠地管理数据的场景中是一个出色且受欢迎的选择。无论开发人员是在处理复杂的键类型、期望可预测的迭代行为,还是提高性能,Map 都是一个强大的工具,可以增强开发人员轻松处理和迭代键值对的能力。