JavaScript-实现数组方法-迭代数组 reduce
·
实现reduce
reduce
参数
- callback(accumulator上次调用callback结果, currentValue当前元素的值, currentIndex当前元素索引,array:调用的数组)
- initialValue 第一次调用回调时初始化accumulator 的值
每次调用的时候 返回值都传递到下一次调用中
这里acc就是前面的元素累加的结果
注意这里首次回调将索引为0的作为
acc索引为1的作为cur
//reduce
let arr = [0, 1, 2, 3, 4]
//累加arr再加10
let result = arr.reduce((acc, cur) => acc + cur, 10) //20
result = arr.reduce((acc, cur) => {
console.log(acc, cur);//01 12 33 64
return acc + cur
}) //10
不对稀疏数组空槽进行调用
和
mapforEachfiltersomeevery一样
this始终是undefine
- 这里非严格模式是window

- 严格模式是
undefined
严格模式下 函数没有被
call apply bind或者通过对象调用 显示绑定this都默认指向undefined
'use strict' //加在开头
//严格模式this始终是undefined
function fn1() {
console.log(this); //undefined
}
fn1()
基于原数组长度迭代
注意这里打印的是cur 第一次回调的cur是arr[1]arr改变了 但是result还是打印原数组迭代的结果
let arr = [0, 1, 2, 3]
let result = arr.reduce((acc, cur) => {
arr.push(cur + 1)
console.log(cur);//123
return acc + cur
}) //
console.log(result, arr); //6 (7) [0, 1, 2, 3, 2, 3, 4]
边界情况
- 提供
initialValue且数组不为空 调用回调函数
arr = [1]
result = arr.reduce((acc, crr) => {
console.log(acc, crr); //10 1
return acc + crr
}, 10)
console.log(result);//11
返回单个值 不执行回调函数
- 数组只有一个元素且未提供
initialValue返回单个值 不调用回调函数
arr = [1]
result = arr.reduce((acc, crr) => {
console.log(acc, crr); //这里没有打印
return acc + crr
})
console.log(result);//1
- 提供了
initialValue且数组为空 不调用回调函数
arr = []
result = arr.reduce((acc, crr) => {
console.log(acc, crr);
return acc + crr
}, 10)
console.log(result);//10
用法
这里参考了mdn
统计对象中值的出现次数
这里的count表示如果出现过相应元素就把次数放进去 如果没出现过就是0 最后都+1
返回的对象{展开前面迭代的对象,当前元素:次数+1}
同一对象字面量内的重复属性直接被覆盖
对象属性名有唯一性key必须唯一
//统计对象中值的出现次数
arr = [1, 2, 2, 3, 2, 4]
result = arr.reduce((all, num) => {
const count = all[num] ?? 0
//返回一个对象
return {
...all,
[num]: count + 1
}
}, {})
console.log(result); //{1: 1, 2: 3, 3: 1, 4: 1}
注意 这里
num是变量 所以要用[num]
迭代过程如图所示
按属性给对象分组
reduce中 key作为分组键按照key进行分组 curGroup判断迭代产生的对象是否有当前处理的对象的key有的话就把那部分也放入key的值中 没有的话返回[]最后就放不进去
返回的对象{展开前面迭代的对象,分组键:[展开这一组,当前对象]}
obj = [{ name: 'a', age: 18, },
{ name: 'b', age: 19 },
{ name: 'c', age: 18, },]
function groupBy(objArr, property) {
return objArr.reduce((acc, obj) => {
const key = obj[property]
const curGroup = acc[key] ?? []
return {
...acc,
[key]: [...curGroup, obj]
}
}, {})
}
const group = groupBy(obj, 'age')
console.log(group);
//{18:[{ name: 'a', age: 18 },{name: 'c', age: 18}],
//19:[{name: 'b', age: 19}]}
迭代过程如图所示
实现
- 判断
acc迭代初始值 这里用了...iValue所以iVallue是剩余参数数组 如果传入iVallue就为iVallue[0]没传入就是this[0]数组的第一位 所以不执行回调函数的情况下 直接返回acc - 处理迭代起始位 这里采用了三元运算符 如果如果传入
iVallue就从数组第1位开始迭代start = 0没传入此时迭代初始值是this[0]从数组的第2位开始start = 1
这里不能用
iValue的真假来判断 因为传入0的时候返回假值 所以需要用剩余参数数组的长度iValue.length > 0来判断是否传入第二个参数
- 这里
len保存原数组长度 - 这里只有在传入
iValue且数组长度>=1的时候 也就是iValue.length + this.length > 2这两个数组的长度加起来>2才执行回调函数 - 循环遍历数组 下一次的
acc就是上一次的迭代完毕的返回值 - 最后返回
acc
代码如下
Array.prototype.myReduce = function (callback, ...iValue) {
let acc = iValue[0] ?? this[0] //迭代初始值
let start = null
start = (iValue.length > 0) ? 0 : 1
let len = this.length //原数组长度
//这种情况下才执行回调函数
if (iValue.length + this.length > 2) {
for (let i = start; i < len; i++) {
if (this[i] !== undefined) {
acc = callback(acc, this[i]) //下一次的acc就是上一次的迭代完毕
}
}
}
return acc
}
测试用例如下
//iValue参数
arr = [1, 2, 3]
result = arr.myReduce((acc, cur) => {
return acc + cur
}, 6)//12
//不执行回调函数的情况
arr = []
result = arr.myReduce((acc, cur) => {
console.log(acc, cur);
return acc + cur
}, 1) //1
arr = [1]
result = arr.myReduce((acc, cur) => {
console.log(acc, cur);
return acc + cur
}) //1
//迭代效果
arr = [1, 2, 3, 4, 5]
result = arr.myReduce((acc, cur) => {
console.log(acc, cur);
return acc + cur
})
let Result = arr.reduce((acc, cur) => {
console.log('应该输出的结果', acc, cur);
return acc + cur
})
console.log('输出结果比较', result, Result);
//不对稀疏数组空槽调用
arr = [1, 2, 3]
arr[6] = 6
result = arr.myReduce((acc, cur) => {
console.log(acc, cur);
return acc + cur
})
//基于原数组长度迭代
arr = [1, 2, 3]
result = arr.myReduce((acc, cur) => {
arr.push(8)
return acc + cur
}) //6
console.log(arr); //[1, 2, 3, 8, 8]
//统计对象中值出现的次数
let stats = [1, 2, 3, 2, 4]
result = stats.myReduce((obj, num) => {
let count = obj[num] ?? 0
return {
...obj,
[num]: count + 1
}
}, {})
console.log(result);
更多推荐




所有评论(0)