ES6 中的 Set和 Map 对比

ES6 中的 SetMap 都是用于存储数据的集合类型,但它们在用途、数据结构和操作方式上有显著区别。以下是它们的核心差异:


1. 数据存储类型

  • Set

    • 存储唯一值(重复值会被自动去重)。
    • 值可以是任意类型(对象、原始值等)。
    • 类似数组,但成员唯一且无序(ES6 规范未定义顺序,但现代浏览器通常按插入顺序存储)。
    • 示例:
      const set = new Set([1, 2, 2, 'a']); // Set {1, 2, 'a'}
  • Map

    • 存储键值对key-value),键和值都可以是任意类型。
    • 键是唯一的(重复键会覆盖之前的值)。
    • 类似对象,但键不限于字符串(可以是对象、函数等)。
    • 示例:
      const map = new Map([['a', 1], [1, 'b'], [{x: 1}, 'c']]); // Map { 'a' => 1, 1 => 'b', {x: 1} => 'c' }

2. 键(Key)的处理

  • Set

    • 没有键的概念,只有值(可以理解为值本身既是键也是值)。
    • 通过值来检查存在性或删除:
      set.has(2); // true set.delete('a');
  • Map

    • 通过键来访问或操作值:
      map.get('a'); // 1 map.set('newKey', 'value'); map.delete(1); // 删除键为 1 的项

3. 性能与使用场景

  • Set

    • 适合需要快速去重或检查值是否存在的场景(如黑名单、去重数组)。
    • 操作复杂度:
      • 添加/删除/检查:平均 O(1)。
  • Map

    • 适合需要关联键值对的场景(如缓存、字典、计数器)。
    • 相比普通对象({}),Map 的键更灵活,且能保持插入顺序。
    • 操作复杂度:
      • 添加/删除/检查:平均 O(1)。

4. 迭代方式

  • Set

    • 迭代时直接获取值:
      set.forEach(value => console.log(value)); for (const value of set) { /* ... */ }
  • Map

    • 迭代时可以分别获取键和值:
      map.forEach((value, key) => console.log(key, value)); for (const [key, value] of map) { /* ... */ }

5. 与对象的区别

  • Set vs 对象

    • 对象通过属性名(字符串/Symbol)访问值,而 Set 通过值本身操作。
    • 对象无法直接判断某个值是否作为属性存在(需 Object.prototype.hasOwnProperty),而 Set 的 has() 方法更直观。
  • Map vs 对象

    • 对象的键只能是字符串或 Symbol,而 Map 的键可以是任意类型。
    • Map 维护插入顺序,而普通对象的属性顺序在 ES6 前是不确定的(ES6 后部分场景有规定顺序)。
    • Map 的实例方法(如 sizeclear())比操作对象属性更方便。

总结表

特性SetMap
存储内容唯一值唯一键值对
键的类型无(值即键)任意类型
去重自动去重键唯一,值可重复
主要方法add(), has(), delete()set(), get(), has()
迭代返回值[key, value] 数组
典型用途去重、集合操作字典、缓存、计数器

示例对比

// Set 示例 const uniqueNumbers = new Set([1, 2, 2, 3]); uniqueNumbers.add(4); console.log(uniqueNumbers.has(2)); // true // Map 示例 const userRoles = new Map(); userRoles.set('Alice', 'Admin'); userRoles.set('Bob', 'User'); console.log(userRoles.get('Alice')); // 'Admin'

根据需求选择:需要唯一值集合用 Set,需要键值对关联用 Map