为何JavaScript中Array.reduce()的两个计数器实现效果不同?
JavaScript Array.reduce()中两种累加写法的差异原因
问题描述
在以下两个Array.reduce()示例中,为何第二个reducer里的count能正常递增,而第一个却始终保持初始值?同时需要解决为初始对象部分属性自定义名称的场景需求。
示例1:count无法递增的写法
const data = [1,2,3,4]; data.reduce((accumulator) => { let { count } = accumulator; count++; console.log(accumulator); return accumulator; }, { count: 0 }); /* 输出结果: { count: 0 } { count: 0 } { count: 0 } { count: 0 } */
示例2:count正常递增的写法
data.reduce((accumulator) => { accumulator.count++; console.log(accumulator); return accumulator; }, { count: 0 }); /* 输出结果: { count: 1 } { count: 2 } { count: 3 } { count: 4 } */
核心原因
基本类型与引用类型的传递差异
- 示例1中,
let { count } = accumulator是解构赋值,这里的count是数字类型(基本类型)。基本类型在赋值时是值传递——相当于把accumulator.count的数值复制了一份给新变量count。后续执行count++只是修改了这个副本,完全没改动原对象accumulator里的count属性,所以每次打印原对象都是初始值0。 - 示例2中,
accumulator.count++是直接操作原对象的属性。对象属于引用类型,操作对象属性时直接修改的是原对象本身,所以每次递增都会改变原对象的count值,打印结果自然是递增的。
自定义属性名称的解决方法
如果需要解构时自定义属性名称(比如把count重命名为customCount),同时要修改属性值,可以用以下两种方式:
方式1:修改原对象属性
data.reduce((accumulator) => { // 解构时自定义属性名 let { count: customCount } = accumulator; customCount++; // 将修改后的值赋值回原对象的属性 accumulator.count = customCount; console.log(accumulator); return accumulator; }, { count: 0 });
方式2:返回新对象(无副作用)
如果不想修改原对象,而是返回一个新对象,适合纯函数场景:
data.reduce((accumulator) => { let { count: customCount } = accumulator; customCount++; // 展开原对象,覆盖count属性 const newAccumulator = { ...accumulator, count: customCount }; console.log(newAccumulator); return newAccumulator; }, { count: 0 });
内容的提问来源于stack exchange,提问作者deekay0
相关产品推荐
相关产品推荐

