JS使用reduce统计数组元素重复次数时方括号与点符号输出差异问题
问题原因分析
核心区别:点表示法 vs 方括号表示法
- 点表示法后面的字段会被当成固定的字符串字面量,不会被解析为变量
- 方括号内的内容会先计算取值,再将计算结果作为属性名访问
代码运行逻辑拆解
你提供的测试代码整理如下:
let data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck', 'Pogo ']; // 方括号写法,结果正常 let instance_1 = data.reduce((acc, elm) => { if(!acc[elm]){ acc[elm] = 0; } acc[elm]++; return acc; }, {}) console.log(instance_1) // 点表示法,结果异常 let instance_2 = data.reduce((acc, elm) => { if(!acc.elm) { acc.elm = 0; } acc.elm++; return acc; }, {}) console.log(instance_2);
instance_1 输出正常的原因
你用acc[elm]访问属性时,方括号里的elm会被解析为当前遍历到的数组元素值,比如第一次循环elm是'car',就等价于访问acc['car'],后续循环会根据当前元素值动态切换访问的属性名,累加后就能得到每个元素的出现次数。
最终instance_1的输出为:
{ car: 5, truck: 3, bike: 2, walk: 2, van: 2, 'Pogo ': 1 }
instance_2 输出异常的原因
你用acc.elm访问属性时,这里的elm不会被识别为你定义的循环变量,而是被当成一个名字叫elm的固定属性,和你当前遍历的元素值完全无关。整个reduce循环的15次遍历,每次都是给acc.elm这个属性累加1,所以最终instance_2的输出只会是:
{ elm: 15 }
使用建议
- 如果你要访问的属性名是固定、符合标识符命名规范的,用点表示法更简洁,比如
obj.name、obj.age - 如果你要访问的属性名是动态变量、包含特殊字符/空格/数字开头,必须用方括号表示法,你的统计场景属于动态属性名的情况,只能用方括号实现。
内容的提问来源于stack exchange,提问作者BlackWatch021
相关产品推荐
相关产品推荐

