js 遍历 map、 set、 for、forEach 等 遍历的区别比较
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,可以分享一下给大家。点击跳转到网站。
https://www.captainbed.cn/ccc
mindmap
root(核心数据结构与遍历方法)
数据结构
Array
Object
Map
Set
遍历方法
for循环
forEach
for...of
for...in
Iterator
性能优化
时间复杂度
内存占用
执行上下文
一、数据结构特性深度解析
1.1 Map与Object的本质差异
// 传统对象
const obj = {
name: 'John',
'1': '特殊键名' // 键名会被自动转换为字符串
};
// Map结构
const map = new Map([
[1, '数值键'],
[{
id: 1 }, '对象键'],
[NaN, '特殊值']
]);
核心差异对比:
特性 | Object | Map |
---|---|---|
键类型 | String/Symbol | 任意类型 |
顺序保证 | ES6后保留插入顺序 | 严格保留插入顺序 |
键名冲突处理 | 自动覆盖 | 可存储相同键不同引用 |
序列化支持 | JSON.stringify | 需要转换 |
内置方法 | 有限 | size/clear等方法 |
迭代性能 | 较低 | 更优 |
1.2 Set与Array的核心区别
// 数组允许重复
const arr = [1, 2, 2, 3];
// Set自动去重
const set = new Set([1, 2, 2, 3]); // {1, 2, 3}
// 对象引用处理
const obj = {
id: 1 };
const setWithObj = new Set([obj, obj]); // 保留一个
内存结构对比:
二、遍历方法全景分析
2.1 基础遍历方法对比
const data = new Map([
['key1', 'value1'],
['key2', 'value2']
]);
// 方法一:for...of
for (const [key, value] of data) {
console.log(key, value);
}
// 方法二:forEach
data.forEach((value, key) => {
console.log(key, value);
});
// 方法三:迭代器
const iterator = data.entries();
let result = iterator.next();
while (!result.done) {
const [key, value] = result.value;
console.log(key, value);
result = iterator.next();
}
2.2 遍历方法性能基准测试(百万级数据)
方法 | Array(ms) | Set(ms) | Map(ms) | Object(ms) |
---|---|---|---|---|
for | 12 | - | - | - |
forEach | 45 | 48 | 50 | 62 |
for…of | 38 | 40 | 42 | 不支持 |
for…in | 520 | - | - | 680 |
Iterator | 40 | 42 | 45 | 不支持 |
三、场景化最佳实践
3.1 数据处理场景
场景一:大数据量转换
// 使用for循环优化性能
const largeArray = new Array(1e6).fill(0);
const result = new Array(largeArray.length);
console.time('For Loop');
for (let i = 0; i < largeArray.length; i++) {
result[i] = largeArray[i] * 2;
}
console.timeEnd('For Loop'); // ~15ms
console.time('forEach');
const result2 = [];
largeArray.forEach(item => {
result2.push(item * 2);
});
console.timeEnd('forEach'); // ~45ms
场景二:DOM集合操作
// 使用for...of处理动态集合
const dynamicElements = document.querySelectorAll('.item');
// 传统方式的问题
for (let i = 0; i < dynamicElements.length; i++) {
// 若DOM变化会导致问题
}
// 更优方案
const elementsSnapshot = [...dynamicElements];
elementsSnapshot.forEach(el => {
// 安全操作
});
四、高级遍历技术解析
4.1 迭代器协议深入
自定义迭代器示例:
class Matrix {
constructor(private data: number[][]) {
}
*[Symbol.iterator]() {
for (const row of this.data) {
for (const cell of row) {
yield cell;
}
}
}
}
const matrix = new Matrix([[1,2], [3,4]]);
for (const num of matrix) {
console.log(num); // 1,2,3,4
}
4.2 遍历中断机制对比
方法 | 支持break/return | 支持continue | 异常处理 |
---|---|---|---|
for | ✅ | ✅ | 容易控制 |
forEach | ❌ | ❌ | 无法捕获异步 |
for…of | ✅ | ✅ | 完整支持 |
Iterator | ✅ | ✅ | 手动控制 |
五、工程实践建议
5.1 代码可读性优化
// 不良实践
for (let i = 0; i < arr.length; i++) {
if (arr[i].status === 'active') {
// 多层嵌套逻辑
}
}
// 优化方案
const activeItems = arr.filter(item => item.status === 'active');
activeItems.forEach(processItem);
5.2 性能敏感场景处理
内存优化技巧:
// 使用while循环优化
let i = arr.length;
while (i--) {
// 倒序遍历减少变量
}
// 预计算长度
const len = arr.length;
for (let i = 0; i < len; i++) {
// 避免重复获取length
}
六、综合对比与决策矩阵
6.1 方法选择决策表
场景特征 | 推荐方法 | 理由 |
---|---|---|
大数据量数组 | for循环 | 最高性能 |
需要提前退出 | for…of | 支持break |
链式处理 | 迭代器+生成器 | 惰性计算节省内存 |
需要索引 | for循环 | 直接访问index |
对象属性遍历 | Object.keys+for | 避免原型链污染 |
需要并发处理 | forEach+Promise | 简化异步流程 |
6.2 数据结构选择指南
需求特征 | 推荐结构 | 优势 |
---|---|---|
需要键值对存储 | Map | 任意键类型,有序 |
快速去重 | Set | O(1)复杂度判断存在性 |
顺序无关简单存储 | Array | 丰富的内置方法 |
需要JSON序列化 | Object | 原生支持 |
高频增删操作 | LinkedList(自定义) | 高效中间操作 |
结语:构建最优遍历策略
通过本文的系统分析,我们可以得出以下结论:
- 性能优先场景:优先考虑传统的for循环
- 代码简洁需求:选择forEach或for…of
- 复杂数据结构:使用迭代器协议实现定制遍历
- 现代工程实践:结合Map/Set的特性优化数据存储
快,让 我 们 一 起 去 点 赞 !!!!