ES6 中的 Map 与 Set 使用详解及遇到的问题

ES6 新增了许多对 JavaScript 语言功能的扩展,其中最重要的是对集合类型的全面支持,尤其是 Map 和 Set 类型。Map 类型允许我们使用任意类型的值作为键,而 Set 类型则是一组独一无二的值。本文将详细讲解 Map 和 Set 类型的使用方法和常见问题。

Map 类型

Map 类型是一种键值对的集合(类似于普通 JavaScript 对象),其中“键”可以是任何类型的值,而“值”可以是任何类型的值。其中最重要的是 Map 类型支持迭代器(Iterator)和 for..of 循环,我们可以通过以下方式创建一个 Map 对象:

let map = new Map([["key1", "value1"], ["key2", "value2"]]);

Map 的访问方式与普通 JavaScript 对象类似,可以使用 get 方法获取值:

console.log(map.get("key1")); // 输出:value1

还可以使用 set 方法添加新的键值对:

map.set("key3", "value3");
console.log(map.get("key3")); // 输出:value3

如果使用相同的键添加新的键值对,则之前的键值对将被替换:

map.set("key1", "new value1");
console.log(map.get("key1")); // 输出:new value1

Map 类型还提供了一些其他有用的方法,比如 size 属性(返回 Map 对象中元素的数量)、has 方法(判断键是否存在)、forEach 方法(遍历 Map 中的所有键值对)。例如,以下代码演示了如何使用 forEach 方法遍历 Map 中所有的键值对:

map.forEach((value, key) => {
  console.log(key + " = " + value); // 输出:key1 = new value1,key2 = value2,key3 = value3
});

Set 类型

Set 类型是一组独一无二的值集合。与 Map 不同,Set 中的每个值本身就是键。我们可以使用以下代码创建一个 Set 对象:

let set = new Set(["value1", "value2", "value3"]);

可以使用 add 方法为 Set 添加新值,使用 delete 方法删除值,使用 has 方法判断值是否存在,如下所示:

set.add("value4");
set.delete("value2");
console.log(set.has("value3")); // 输出:true

Set 类型还提供了一些其他有用的方法,比如 size 属性(返回 Set 对象中元素的数量)、forEach 方法(遍历 Set 中的所有值)。例如,以下代码演示了如何使用 forEach 方法遍历 Set 中所有的值:

set.forEach((value) => {
  console.log(value); // 输出:value1,value3,value4
});

遇到的问题

尽管 Map 和 Set 的使用方法非常简单,但如果没有明确理解它们的行为,可能会在使用过程中遇到一些麻烦。以下是一些常见问题及其解决方法:

问题 1:在 Map 中比较两个对象是否相等时,始终返回 false

原因:JavaScript 中对象比较是基于对象引用,而不是对象内容的相等性。

解决方法:在 Map 中比较对象时,我们必须使用一个唯一标识符(对象属性或唯一 ID 等)来代表对象。例如,以下代码展示了如何使用对象属性作为唯一标识符:

let obj1 = { id: 1, name: "John Doe" };
let obj2 = { id: 2, name: "Jane Doe" };
let map = new Map([[obj1.id, obj1], [obj2.id, obj2]]);
console.log(map.get(1).name); // 输出:John Doe

问题 2:使用 for..of 循环遍历 Map 时,输出的键值对顺序与添加时不同

原因:原因在于 Map 使用了哈希表(Hash Table)实现,因此哈希表本身是无序的。

解决方法:如果需要按照某种顺序遍历 Map 中的元素,则必须手动对其进行排序,或者使用一个数组来记录键的顺序,例如:

let map = new Map([['a', 1], ['b', 2], ['c', 3]]);
let keys = [...map.keys()].sort(); // 对键进行排序
for (let key of keys) {
  console.log(key + ' = ' + map.get(key)); // 按键排序输出键值对
}

问题 3:使用 Set 时,如何确保不同数据类型的值被视为不同的值

原因:在 JavaScript 中,0 和 -0 是相同的,NaN 与 NaN 也是相同的。

解决方法:我们可以使用以下代码创建一个新的类,它能够比较任意类型的值,并将其视为不同的值:

class UniqueKey {
  constructor() {
    this.counter = 0;
  }
  next() {
    return this.counter++;
  }
}

let uniqueKey = new UniqueKey();
let set = new Set([uniqueKey.next(), uniqueKey.next(), {}]);
console.log(set.size); // 输出:3

总结

Map 和 Set 类型是 JavaScript 中一个重要的新增特性,可以有效地简化数据结构和算法的实现。在使用 Map 和 Set 时,需要注意避免常见的问题,同时也要注意它们的适用范围和局限性。希望本文对初学者有所帮助。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65966241eb4cecbf2da378f5


纠错反馈