前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库Map 迭代顺序与对象属性顺序
JavaScript数组与集合

Map 的遍历顺序是怎么定的,和对象的属性顺序有什么区别?

Map 严格按键第一次插入的顺序遍历。对已有的键再 set 只是改值,位置不变;先 delete 再 set 才会排到最后。普通对象不一样,像 "2"、"10" 这样的整数键会按数值从小到大排在最前面,其余字符串键才按插入顺序。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#数组与集合
先看核心答案读代码示例
理解线索

两种容器的顺序规则

  1. Map键第一次插入的先后,更新值不影响顺序
  2. 对象的整数键"2"、"10" 这类键按数值从小到大,排在最前面
  3. 对象的其他键普通字符串键按创建顺序,Symbol 键排在最后

"02" 和 "-1" 都不算整数键,它们在对象里按普通字符串键处理,按插入顺序排,不会被挪到前面。

核心回答

先记住这个答案

Map 按键第一次被插入的顺序遍历,不管键是字符串、数字还是对象。对一个已经存在的键再调用 set,只会更新值,它在遍历里的位置不变;先 delete 再 set,才算重新插入,会排到最后。普通对象的规则复杂一些:像 "2"、"10" 这样的整数键,会按数值从小到大排在最前面,其余的字符串键按创建顺序排在后面,Symbol 键排在最后,而且 Object.keys 根本不返回 Symbol 键。

  • Map 按插入顺序遍历,和键的类型无关
  • 对已有键 set 只改值,不改位置
  • 先 delete 再 set,键才会移到最后
  • 对象的整数键按数值升序,排在其他键前面

同样的插入顺序,两种结果

先插入 '10',再插入 '2',分别放进 Map 和普通对象,然后试一下更新和删除后重新插入。

插入、更新和删除重插JavaScript
const map = new Map([['10', 'ten'], ['2', 'two']])
const object = { '10': 'ten', '2': 'two' }

console.log(JSON.stringify([...map.keys()]))     // Map 按插入顺序
console.log(JSON.stringify(Object.keys(object))) // 对象按整数大小

map.set('10', 'updated')                         // 更新已有键
console.log(JSON.stringify([...map.keys()]))

map.delete('10')
map.set('10', 'again')                           // 删除后重新插入
console.log(JSON.stringify([...map.keys()]))
查看输出与解释
["10","2"]
["2","10"]
["10","2"]
["2","10"]

前两行是同样的插入顺序,Map 保持了 '10' 在前,对象却把 '2' 排到了前面,因为这两个键都是整数形式的字符串,对象会按数值排。第三行说明更新值不改位置。第四行删除后再插入,'10' 才跑到最后。

用 Map 实现 LRU 缓存

LRU 缓存的意思是容量满了就淘汰最久没用过的那一项。Map 的插入顺序正好能用来记录「谁最久没用」:最前面的就是最老的。

访问时先删再插
读取一个键时,要把它挪到最后,表示刚刚用过。但只调用 set 是不行的,前面说过更新值不会改变位置。正确做法是先 delete 再 set。容量超了就删掉第一个键,用 map.keys().next().value 就能拿到它。 这是面试手写 LRU 最常见的解法,每次读写都是 O(1)。关键就在于分清「更新」和「重新插入」对顺序的影响不同。
回答前,多想一步

容易答错的地方

以为对已有键 set 会把它移到最后
set 已有的键只改值,位置不动。需要刷新顺序,必须先 delete 再 set。
说对象的属性顺序是随机的
现在的规范对对象自有属性的顺序有明确规则:整数键按数值升序在前,字符串键按创建顺序在中间,Symbol 键按创建顺序在最后。ES2015 先给 Reflect.ownKeys 这类方法定了这个顺序,ES2020 又把 Object.keys 和 for...in 也统一了进来,只是 Object.keys 不含 Symbol 键。
用对象的键顺序代替业务排序
如果表格要按编号排序,应该显式调用 sort。依赖对象恰好把整数键排好,一旦编号变成 "A01" 或带前导零的 "007",排序就不成立了。
试着用自己的话回答

面试官还会怎么问?

键 "02" 会和 "2" 一样被排到前面吗?

不会。只有标准的整数形式才会被当成整数键,"02" 转成数字再转回字符串是 "2",和原来不一致,所以它是普通字符串键,按插入顺序排。

用对象当 Map 的键,改了对象的字段会影响顺序吗?

不会。Map 按对象的引用识别键,改字段不改引用,还是同一个键,位置不变。

把 Map 转成对象,顺序还在吗?

不一定。Object.fromEntries(map) 之后,整数形式的键会被挪到前面,原来的插入顺序就乱了。而且非字符串的键会被转成字符串,数字 1 和字符串 '1' 会合并成一个。需要保留顺序和键类型,就转成条目数组 [...map]。

从一道题,走向一组知识

把知识连起来

数组与集合

JSON.stringify(Map) 为什么得到空对象,怎样可靠保存再恢复?

Map 转成条目数组再存成 JSON 能保留插入顺序,转成普通对象就可能被整数键规则打乱。

数组与集合

Map.set 和 Set.add 为什么能链式调用,delete、clear 可以吗?

set 返回 Map 本身所以能链式调用,这里讲的是 set 对已有键不改变位置。

参考资料

  • MDN:Map 与对象差异

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 同样的插入顺序,两种结果
  3. 用 Map 实现 LRU 缓存
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑