
**作者**:watermelo37 CSDN全栈领域优质创作者、万粉博主、华为云云享专家、阿里云专家博主、腾讯云“创作之星”特邀作者、支付宝合作作者,全平台博客昵称watermelo37。 一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、LLM均有涉猎。undefined 温柔地对待温柔的人,包容的三观就是最大的温柔。undefined


在前端开发中,我们经常用 Map 来存储键值对,比如缓存接口请求结果、维护用户状态或统计访问数据。最常用的 Map 基本方法包括get / set / has,可Map能不能像数组那样,获取第 i 个元素呢? 首先我们可以迅速想到,Map的添加是有顺序的,按顺序提取绝对可行,那么我们可以写一个新对象,比如叫orderMap,它既支持map的原生方法,又可以像数组那样获取第 i 个元素:function createOrderMap() {
const keys = [];
const values = [];
return {
set(key, value) {
const index = keys.indexOf(key);
if (index >= 0) {
// key 已存在,更新对应 value
values[index] = value;
} else {
// key 不存在,新增
keys.push(key);
values.push(value);
}
},
// 按索引访问元素,返回 [key, value]
getByIndex(i) {
if (i < 0 || i >= keys.length) return undefined;
return [keys[i], values[i]];
},
length() {
return keys.length;
}
// ...还有has、get等方法暂不实现
};
}
// 测试
const orderMap = createOrderMap();
orderMap.set('a', 1);
orderMap.set('b', 2);
orderMap.set('c', 3);
// 覆盖 b
orderMap.set('b', 22);
console.log(orderMap.getByIndex(0)); // ['a', 1]
console.log(orderMap.getByIndex(1)); // ['b', 22]
console.log(orderMap.getByIndex(2)); // ['c', 3]
console.log(orderMap.length()); // 3 当然上述只是一种处于技术偏好的“玩耍”,那原生的Map对象到底是不是有序的呢?答案是肯定的。在特定操作下,我们可以像数组一样“按顺序访问元素”。那原生Map对象如何获取第二个元素呢? 假设我们在做一个用户访问记录的功能,每次用户访问页面时,我们把用户 ID 和访问时间记录在 Map 里:const userVisits = new Map();
userVisits.set('user1', '2025-08-31T09:00:00');
userVisits.set('user2', '2025-08-31T09:05:00');
userVisits.set('user3', '2025-08-31T09:10:00'); 现在我们想获取第二个访问的用户信息,即 Map 中的第二个 [key, value] 对。 Map 可以通过 Array.from() 转成数组,然后用索引直接访问:const secondEntry = Array.from(userVisits)[1];
console.log(secondEntry); // ['user2', '2025-08-31T09:05:00']
console.log(secondEntry[0]); // 'user2'
console.log(secondEntry[1]); // '2025-08-31T09:05:00' 这样语法简单,直接通过索引访问。但是Map 转成数组会创建一个新数组,如果 Map 很大,会消耗额外内存。 Map 本身是可迭代对象,它的 entries()、keys()、values() 方法返回的都是 迭代器(Iterator)。迭代器允许我们按顺序访问每一个元素,而不需要转成数组。const iterator = userVisits.entries(); // entries() 返回 [key, value] 迭代器
iterator.next(); // 跳过第一个
const second = iterator.next().value;
console.log(second); // ['user2', '2025-08-31T09:05:00']
console.log(second[0]); // 'user2'
console.log(second[1]); // '2025-08-31T09:05:00' 看到这里,熟悉Array.from()的开发者可能已经发现了什么:Map 之所以能用 Array.from() 转换为数组,是因为它是一个实现了 [Symbol.iterator] 的可迭代对象,Array.from() 能够将任何可迭代对象(或类数组对象)转换为数组。对于 Map 而言,它的默认迭代结果是 [key, value] 形式的 entry,因此 Array.from(map) 得到的是一个二维数组。 set可以直接利用可迭代对象的性质来遍历:let set = new Set([10, 20, 30]);
let i = 0;
let targetIndex = 1; // 想取第 2 个元素
for (let item of set) {
if (i === targetIndex) {
console.log(item); // 20
break;
}
i++;
} 或者一样转换成迭代器再用next():const set = new Set([10, 20, 30]);
// 1. 获取迭代器
const iterator = set.values();
// 2. 调用 next()
console.log(iterator.next()); // { value: 10, done: false }
console.log(iterator.next()); // { value: 20, done: false }
console.log(iterator.next()); // { value: 30, done: false }
console.log(iterator.next()); // { value: undefined, done: true } 也可以封装一个迭代器获取方法,这样set、map,甚至普通数组和字符串都可以通用了:function getNth(iterable, n) {
let iter = iterable[Symbol.iterator]();
let result;
while (n-- >= 0) {
result = iter.next();
if (result.done) return undefined; // 超出范围
}
return result.value;
}
console.log(getNth(new Set([10, 20, 30]), 2)); // 30
console.log(getNth("hello", 1)); // "e" 迭代器是一个对象,遵循 { value, done } 结构,value 是当前元素,done 是布尔值表示是否遍历完。 **不可以**,迭代器是一次性的。如果想重新遍历,必须重新调用 entries() 或 keys() / values()。熟悉数据结构的开发者可以把他理解成一个单向链表。
// 遍历迭代器,无法回头望
const it2 = userVisits.entries();
for (const [user, time] of it2) {
console.log(user, time);
} 只要一个对象实现了 Symbol.iterator 方法,就叫可迭代对象。比如 Array、String、Set、Map、arguments、NodeList 等。 它们可以用:for...of、扩展运算符 ...、Array.from()、解构赋值 [a, b, c] = ... 但是它们自己不一定有 next() 方法。 迭代器是实现了 next() 方法的对象,且next() 返回一个 { value, done } 对象。迭代器是真正“驱动”迭代过程的东西。 使用的时候搭配 for...of 循环遍历即可,语法简洁。
提取 Map 第二个元素的常用方法:①转成数组(简单直观,但有内存开销)。②使用迭代器(更灵活、节省内存)。 迭代器每次调用 .next() 返回 { value, done },可以控制遍历流程,比如“跳过前几个元素”或“取前 n 个元素”。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~ 其他热门文章,请关注:极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图
你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解
通过array.filter()实现数组的数据筛选、数据清洗和链式调用
测评:这B班上的值不值?在不同城市过上同等生活水平到底需要多少钱?
通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能
TreeSize:免费的磁盘清理与管理神器,解决C盘爆满的燃眉之
通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制
深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解
前端实战:基于Vue3与免费满血版DeepSeek实现无限滚动+懒加载+瀑布流模块及优化策略
el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能
JavaScript双问号操作符(??)详解,解决使用 || 时因类型转换带来的问题
高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图
内存泄漏——海量数据背后隐藏的项目生产环境崩溃风险!如何避免内存泄漏