JavaScript中Map与Object键值互换:为何Map会无限循环?
Map与Object互换键值时循环行为差异的原因
核心差异:迭代器的工作逻辑不同
1. Object的for...in循环:基于固定列表遍历
for...in在启动遍历前,会先收集对象当前所有可枚举属性的键,形成一个固定列表。后续对对象的修改(新增、删除属性)不会影响这个已经确定的遍历列表。
看你的代码执行流程:
const obj = { 1: "one", 2: "two" }; for (const key in obj) { const value = obj[key]; obj[value] = key delete obj[key]; } console.log(obj); // { one: '1', two: '2' }
遍历开始时,for...in已经收集到['1', '2']两个键,哪怕循环中删除了原键、新增了新属性,遍历只会按这个固定列表执行两次,所以是有限循环。
2. Map的for...of循环:基于实时集合遍历
Map的迭代器是动态的,它会直接读取Map当前时刻的键值对集合,而不是先缓存固定列表。
你的Map循环执行流程:
const map = new Map([[1, "one"], [2, "two"]]); for (const [key, value] of map) { map.set(value, key); map.delete(key); }
- 第一次迭代:取出
[1, "one"],删除1并新增"one" => 1,此时Map内容为[[2, "two"], ["one", 1]] - 第二次迭代:取出
[2, "two"],删除2并新增"two" => 2,此时Map内容为[["one", 1], ["two", 2]] - 第三次迭代:取出
["one", 1],删除"one"并新增1 => "one",Map回到[["two", 2], [1, "one"]] - 第四次迭代:取出
["two", 2],删除"two"并新增2 => "two",Map又回到类似初始的状态 - 以此往复,迭代器永远能读到新的键值对,陷入无限循环
让Map实现有限循环的解决办法
如果要安全地给Map互换键值,需要先把原有的键值对拷贝成固定数组,再遍历这个数组操作Map:
const map = new Map([[1, "one"], [2, "two"]]); // 将Map转成数组,脱离原Map的动态集合 for (const [key, value] of Array.from(map)) { map.set(value, key); map.delete(key); } console.log(map); // Map(2) { 'one' => 1, 'two' => 2 }
这样遍历的是初始的固定数组,不受后续Map修改的影响,自然会在两次迭代后结束。
内容的提问来源于stack exchange,提问作者hardy
相关产品推荐
相关产品推荐

