第三十三天:数组扩展 — 展开运算符与便捷查找
蜗牛往上爬 · 前端工业可视化学习笔记 第 33 篇
数组是工业数据的主战场。ES6 给数组带来了展开运算符(...)、find/findIndex、Array.from、includes、flat 等一批利器。今天学完,数据处理会又简洁又强大。
目录
一、展开运算符 …
展开(...)是把数组/对象"打散"——用于合并、复制、传参。
// ===== 合并数组 =====
const a = ["CNC-001", "AGV-002"];
const b = ["ARM-003", "CNC-004"];
const all = [...a, ...b];
// ["CNC-001", "AGV-002", "ARM-003", "CNC-004"]
// ===== 复制数组(浅拷贝)=====
const original = ["CNC-001", "AGV-002"];
const copy = [...original];
copy.push("ARM-003");
console.log(original.length); // 2(原数组没变)
// ===== 传参 =====
const nums = [3, 1, 2];
console.log(Math.max(...nums)); // 3
// ===== 合并对象(对象展开)=====
const base = { name: "CNC-001", temp: 65 };
const ext = { ...base, status: "运行中" };
// { name: "CNC-001", temp: 65, status: "运行中" }
// 覆盖属性(后写覆盖)
const config = { ...base, temp: 85 };
// { name: "CNC-001", temp: 85 }
展开 vs 解构:展开是"打散"(合并/复制/传参),解构是"提取"(取值)。方向相反。
二、find 与 findIndex
const deviceList = [
{ id: "CNC-001", temp: 65 },
{ id: "AGV-002", temp: 42 },
{ id: "ARM-003", temp: 38 }
];
// find:返回第一个满足条件的元素
const target = deviceList.find(d => d.id === "AGV-002");
// { id: "AGV-002", temp: 42 }
// 找不到返回 undefined
// findIndex:返回下标
const index = deviceList.findIndex(d => d.temp > 50);
// 0(CNC-001);找不到返回 -1
// 应用:根据 id 查找并更新
const idToUpdate = "AGV-002";
const device = deviceList.find(d => d.id === idToUpdate);
if (device) {
device.temp = 50;
}
对比 indexOf:indexOf 只能查"值",find 能按"条件"查(尤其是对象数组)。
三、Array.from 与 Array.of
// Array.from:类数组 → 真数组
// 场景 1:arguments
function sumAll() {
const nums = Array.from(arguments);
return nums.reduce((s, n) => s + n, 0);
}
console.log(sumAll(1, 2, 3)); // 6
// 场景 2:NodeList → 可用数组方法
const cards = Array.from(document.querySelectorAll(".card"));
// 场景 3:生成序列(第二参数是映射函数)
const range = Array.from({ length: 5 }, (_, i) => i + 1);
// [1, 2, 3, 4, 5]
const months = Array.from({ length: 12 }, (_, i) => i + 1);
// [1, 2, ..., 12]
// Array.of:创建数组(元素是参数)
const nums = Array.of(1, 2, 3);
// [1, 2, 3]
四、includes 与 flat
// includes(数组版):判断存在
const ids = ["CNC-001", "AGV-002"];
console.log(ids.includes("AGV-002")); // true
console.log(ids.includes("ARM-003")); // false
// 应用:判断是否在监控列表
const monitored = ["CNC-001", "CNC-004"];
const isMonitored = id => monitored.includes(id);
console.log(isMonitored("CNC-001")); // true
// flat:拍平嵌套数组
const nested = [[1, 2], [3, 4]];
console.log(nested.flat()); // [1, 2, 3, 4]
const deep = [1, [2, [3, [4]]]];
console.log(deep.flat(2)); // [1, 2, 3, [4]]
console.log(deep.flat(Infinity)); // [1, 2, 3, 4]
// flatMap:拍平 + 映射(一步)
const devices = [
{ id: "A", sensors: [1, 2] },
{ id: "B", sensors: [3, 4] }
];
const allSensors = devices.flatMap(d => d.sensors);
// [1, 2, 3, 4]
五、sort 排序注意点
// ❌ 数字排序默认按字符串!结果错误
const nums = [3, 10, 1, 20];
console.log(nums.sort()); // [1, 10, 20, 3]
// ✅ 必须传比较函数
console.log(nums.sort((a, b) => a - b)); // [1, 3, 10, 20] 升序
console.log(nums.sort((a, b) => b - a)); // [20, 10, 3, 1] 降序
// 对象数组按属性排序
const deviceList = [
{ id: "CNC-001", temp: 65 },
{ id: "AGV-002", temp: 42 },
{ id: "ARM-003", temp: 38 }
];
const sorted = [...deviceList].sort((a, b) => a.temp - b.temp);
// ⭐ 用 [...arr] 复制,避免 sort 修改原数组
六、综合实战:数据统计面板
const deviceList = [
{ id: "CNC-001", temp: 65, online: true, workshop: "一号车间" },
{ id: "AGV-002", temp: 42, online: true, workshop: "二号车间" },
{ id: "ARM-003", temp: 38, online: false, workshop: "一号车间" },
{ id: "CNC-004", temp: 88, online: true, workshop: "二号车间" }
];
// 在线数量
const onlineCount = deviceList.filter(d => d.online).length; // 3
// 平均温度
const avgTemp = (
deviceList.map(d => d.temp).reduce((s, t) => s + t, 0) /
deviceList.length
).toFixed(1); // "58.3"
// 各车间数量
const byWorkshop = deviceList.reduce((acc, d) => {
acc[d.workshop] = (acc[d.workshop] || 0) + 1;
return acc;
}, {}); // { "一号车间": 2, "二号车间": 2 }
// 高温设备(>50)
const hotIds = deviceList.filter(d => d.temp > 50).map(d => d.id);
// ["CNC-001", "CNC-004"]
// 按温度降序(复制后排序)
const byTemp = [...deviceList].sort((a, b) => b.temp - a.temp);
// CNC-004(88) → CNC-001(65) → AGV-002(42) → ARM-003(38)
// 生成统计面板 HTML(模板字符串 + map + join)
const panelHTML = `
<div class="stat-panel">
<div>在线:<strong>${onlineCount}</strong></div>
<div>均温:<strong>${avgTemp}°C</strong></div>
<div>高温:<strong>${hotIds.length}</strong></div>
<div>车间:<strong>${Object.keys(byWorkshop).length}</strong></div>
</div>
`;
七、总结
🎯 数组扩展学完,数据处理的工具箱就齐全了。下周学对象扩展与 Set/Map——ES6 的数据结构升级。