JavaScript中Map存储数组为空?两段代码结果差异求助
问题分析与解决
问题现象
第一段JavaScript代码运行后,使用console.log输出Map时,所有键对应的数组均显示为空:
let arr1 =[{name:'mani',age:2},{name:'raj',age:2},{name:'s',age:1}]; let test = new Map(); for(const EI of arr1){ if( !test.has(EI.age)){ test.set(EI.age,new Array()); } test.set(EI.age,test.get(EI.age).push(EI) ); }
但第二段统计数字出现次数的代码却能正常运行:
let arr1 =[3,4,5,6,6,7,8,8,8]; let test = new Map(); for(const EI of arr1){ if( !test.has(EI)){ test.set(EI,1); continue; } test.set(EI,test.get(EI) + 1); }
尝试使用test.set(EI,[test.get(EI)].push(1) )的写法,结果仍得到空数组。
问题根源
核心问题出在**Array.push()方法的返回值**上:push()添加元素后,返回的是数组的新长度(数字类型),而不是修改后的数组本身。
第一段代码的执行逻辑存在错误:
- 首次处理某age值时,先给Map对应键设置空数组;
- 接着调用
test.get(EI.age).push(EI),此时返回的是数组长度(比如第一次是1); - 你又用
test.set(EI.age, 长度值)把原来的数组替换成了数字; - 后续再处理同age的元素时,
test.get(EI.age)拿到的是数字,调用数字.push()会静默失败,最终Map里存储的根本不是数组,而是数字——你看到的“空数组”是console的显示异常,实际存储的是数字值。
第二段代码能正常运行,是因为逻辑本身就是要把数字累加后赋值给Map键,和push()的返回值逻辑无关。
正确写法
不需要每次调用set更新Map,因为数组是引用类型,直接修改取出的数组就会同步到Map的存储中:
let arr1 =[{name:'mani',age:2},{name:'raj',age:2},{name:'s',age:1}]; let test = new Map(); for(const EI of arr1){ if( !test.has(EI.age)){ test.set(EI.age, []); } // 直接获取数组并添加元素,无需重新set test.get(EI.age).push(EI); }
或者用更简洁的逻辑:
let arr1 =[{name:'mani',age:2},{name:'raj',age:2},{name:'s',age:1}]; let test = new Map(); for(const EI of arr1){ // 不存在则创建空数组,存在则直接取已有数组 const group = test.get(EI.age) || []; group.push(EI); test.set(EI.age, group); }
内容的提问来源于stack exchange,提问作者Vengatesh Pandiyan
相关产品推荐
相关产品推荐

