【ES6】day35-set-map

作者:mario 发布时间: 2026-08-27 阅读量:4 评论数:0

第三十五天:Set 与 Map — ES6 新数据结构

蜗牛往上爬 · 前端工业可视化学习笔记 第 35 篇
数组和对象用了很多年,ES6 带来了两个新成员:Set(唯一值集合,去重神器)和 Map(真正的键值对,键可以是任何类型)。今天学它们 + 数据结构选型 + 一个综合实战:设备状态管理器。


目录


一、Set:唯一值集合

Set 中的值不重复——天然去重:

const set = new Set();

set.add("CNC-001");
set.add("AGV-002");
set.add("CNC-001");  // 重复,无效
console.log(set.size);  // 2

set.has("CNC-001");  // true(判断存在)
set.delete("AGV-002");
// set.clear()  清空

// 初始化时传数组(自动去重)
const idSet = new Set(["CNC-001", "AGV-002", "CNC-001"]);
console.log(idSet.size);  // 2

二、数组去重(经典用途)

const ids = ["CNC-001", "AGV-002", "CNC-001", "ARM-003", "AGV-002"];

// 一行去重
const unique = [...new Set(ids)];
// ["CNC-001", "AGV-002", "ARM-003"]

// 对象数组按字段去重(借助 Set 记录已见过的值)
const devices = [
  { id: "A", workshop: "一号" },
  { id: "B", workshop: "一号" },
  { id: "C", workshop: "二号" }
];
const seen = new Set();
const uniqueWorkshops = devices.filter(d => {
  if (seen.has(d.workshop)) return false;
  seen.add(d.workshop);
  return true;
});
// [{ id: "A" }, { id: "C" }](每车间保留一台)

三、集合运算

const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4]);

// 并集
const union = new Set([...a, ...b]);       // {1,2,3,4}

// 交集
const intersect = new Set([...a].filter(x => b.has(x)));  // {2,3}

// 差集(a 有 b 没有)
const diff = new Set([...a].filter(x => !b.has(x)));      // {1}

四、Map:真正的键值对

Map vs 对象:对象键只能是字符串,Map 的键可以是任何类型

const map = new Map();

map.set("name", "CNC-001");   // 字符串键
map.set("temp", 65);

// ⭐ 对象键(对象做不到!)
const deviceKey = { id: "CNC-001" };
map.set(deviceKey, { temp: 65, status: "运行中" });

map.get("name");       // "CNC-001"
map.get(deviceKey);    // { temp: 65, status: "运行中" }
map.get("xxx");        // undefined

map.has("temp");  // true
map.size;         // 3
map.delete("temp");

五、Map 的遍历与转换

const statusMap = new Map([
  ["运行中", 12],
  ["待机", 5],
  ["故障", 2]
]);

// for...of + 解构(默认遍历 entries)
for (const [key, value] of statusMap) {
  console.log(`${key}: ${value} 台`);
}

// keys / values
[...statusMap.keys()];    // ["运行中", "待机", "故障"]
[...statusMap.values()];  // [12, 5, 2]

// 求和
const total = [...statusMap.values()].reduce((s, n) => s + n, 0);  // 19

// ===== 与对象互转 =====
// 对象 → Map
const map2 = new Map(Object.entries({ id: "CNC-001", temp: 65 }));
// Map → 对象
const obj = Object.fromEntries(map2);

词频统计(Map 经典应用)

// 统计各设备告警次数
const logs = [
  { device: "CNC-001" }, { device: "AGV-002" },
  { device: "CNC-001" }, { device: "ARM-003" },
  { device: "CNC-001" }
];

const counter = new Map();
for (const { device } of logs) {
  counter.set(device, (counter.get(device) || 0) + 1);
}
console.log([...counter]);
// [["CNC-001", 3], ["AGV-002", 1], ["ARM-003", 1]]

六、数据结构选型

结构

特点

场景

Array

有序、可重复

设备列表、图表数据

Object

键值对(字符串键)

描述单个实体、配置

Set

唯一值

去重、判断存在

Map

任意类型键

动态键、计数、频繁增删

选型决策:
有顺序的一组数据 → 数组
描述一个东西 → 对象
要不重复 / 只判断存在 → Set
键是动态的或非字符串 → Map

性能提示set.has() 是 O(1),arr.includes() 是 O(n)——大数据量频繁判断存在,用 Set。


七、综合实战:设备状态管理器

/**
 * 设备状态管理器:Map 存状态 + Set 管告警/监控
 */
function createDeviceManager() {
  const devices = new Map();   // 设备表:id → 数据
  const monitored = new Set(); // 监控名单
  const alertSet = new Set();  // 告警集合(自动去重)

  return {
    register(id, info = {}) {
      if (devices.has(id)) return false;
      devices.set(id, { id, name: info.name ?? "未知设备",
        temp: info.temp ?? 0, status: info.status ?? "离线", ...info });
      return true;
    },

    update(id, data) {
      const device = devices.get(id);
      if (!device) return console.warn(`${id} 未注册`);

      devices.set(id, { ...device, ...data });

      // 温度告警
      const updated = devices.get(id);
      if (updated.temp >= 80) {
        alertSet.add(id);
        console.warn(`⚠ ${id} 温度告警:${updated.temp}°C`);
      } else {
        alertSet.delete(id);
      }
    },

    watch(id) { monitored.add(id); },
    unwatch(id) { monitored.delete(id); },

    get(id) { return devices.get(id) ?? null; },
    getAlerts() { return [...alertSet]; },

    // 词频统计:各状态数量
    getStatusCount() {
      const counter = new Map();
      for (const { status } of devices.values()) {
        counter.set(status, (counter.get(status) || 0) + 1);
      }
      return Object.fromEntries(counter);
    },

    // 监控且在线的设备(可选链安全访问)
    getMonitoredOnline() {
      return [...monitored].filter(id =>
        devices.get(id)?.status === "运行中");
    }
  };
}

// 使用
const manager = createDeviceManager();
manager.register("CNC-001", { name: "数控机床", temp: 65, status: "运行中" });
manager.register("AGV-002", { name: "搬运机器人", temp: 42, status: "运行中" });
manager.watch("CNC-001");

manager.update("CNC-001", { temp: 85 });  // ⚠ 触发告警
console.log(manager.getAlerts());          // ["CNC-001"]
console.log(manager.getStatusCount());     // { "运行中": 2 }

manager.update("CNC-001", { temp: 60 });   // 恢复
console.log(manager.getAlerts());          // []

这个管理器用上了:Map(动态键值)、Set(唯一集合)、展开(合并更新)、??(兜底)、?.(安全访问)、词频统计——本周全部知识。


八、总结

结构

核心 API

一句话

Set

add / has / delete / size

唯一值集合,去重神器

Map

set / get / has / delete / size

任意类型键的键值对

去重

[...new Set(arr)]

一行搞定

互转

Object.entries / fromEntries

对象 ↔ Map

词频

map.set(k, (map.get(k)||0)+1)

统计计数模板

🎯 Set 和 Map 补齐了数据结构版图。下周进入 ES6 的重头戏:异步编程(Promise / async await)——大屏数据请求的基础!

评论