这是我参与更文挑战的第 31 天,活动详情查看 更文挑战
虽然已经不是挑战了,但还是要写,接下来是自己的挑战
这个系列也没啥花头,就是来整平时面试的一些手写函数,考这些简单实现的好处是能看出基本编码水平,且占用时间不长,更全面地看出你的代码实力如何。一般不会出有很多边界条件的问题,那样面试时间不够用,考察不全面。
平时被考到的 api 如果不知道或不清楚,直接问面试官就行, api 怎么用这些 Google 下谁都能马上了解的知识也看不出水平。关键是在实现过程,和你的编码状态、习惯、思路清晰程度等。
注意是简单实现,不是完整实现,重要的是概念清晰和实现思路清晰,建议
先解释清除概念
=>写用例
=>写伪代码
=>再实现具体功能
,再优化
,一步步来。
昨天我们看了数组 map(), filter()
的手写实现 今天试试 reduce()
23. Array.prototype.reduce()
是什么
reduce()
方法对数组中的每个元素执行一个由您提供的reducer
函数(升序执行),将其结果汇总为单个返回值
。
例子
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15
// 5 作为参数是初始值
复制代码
reducer 函数接收4个参数:
- Accumulator (acc) (累计器)
- Current Value (cur) (当前值)
- Current Index (idx) (当前索引)
- Source Array (src) (源数组)
您的 reducer
函数的返回值分配给累计器,该返回值在数组的每个迭代中被记住
,并最后成为最终的单个结果值。
语法
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
复制代码
参数
callback
- 执行数组中每个值 (如果没有提供 initialValue 则第一个值除外)的函数,包含四个参数:
accumulator
: 累计器累计回调的返回值
; 它是上一次调用回调时返回的累积值,或initialValue(见于下方)。currentValue
数组中正在处理的元素。index
可选: 数组中正在处理的当前元素的索引。如果提供了initialValue
,则起始索引号为0
,否则从索引1
起始。array
可选: 调用reduce()的数组
- 执行数组中每个值 (如果没有提供 initialValue 则第一个值除外)的函数,包含四个参数:
initialValue
可选- 作为
第一次调用
callback
函数时的第一个参数的值
(初始值)。 如果没有提供初始值,则将使用数组中的第一个元素。 - 在没有初始值的空数组上调用 reduce 将报错。
- 作为
返回值
函数累计处理的结果。
关于 reduce 的更多用法建议参考 MDN
reduce 的英文含义是 减少,减轻,节减;缩短,缩小;降低
,可以想象成一个数组,经过 reduce
“缩减”成一个值。
或者说,对这个数组迭代地进行处理,最后返回一个汇总结果。
手写实现
我们实现前再总结下重点:
reduce
为数组中的每一个元素依次执行callback函数
,(不包括数组中被删除或从未被赋值的元素),接受四个参数:
- accumulator 累计器
- currentValue 当前值
- currentIndex 当前索引
- array 数组
回调函数第一次执行时,accumulator
和 currentValue
的取值有两种情况:
- 如果提供了 initialValue:
accumulator
取值为 initialValuecurrentValue
取数组中的第一个值
- 如果没有提供
initialValue
,那么:
accumulator
取数组中的第一个值currentValue
取数组中的第二个值。- 在没有初始值的空数组上调用 reduce 将报错。
在看实现代码之前,建议先看上篇 map实现 , 很多思想都是相同的
Array.prototype.myReduce = function(callback, initialValue) {
if (this == null) {
throw new TypeError("Cannot read property 'reduce' of null or undefined");
}
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function')
}
let O = Object(this)
// 最后返回结果是最后的累计 accumulator
let accumulator
let k = 0
// 初始值条件判断
if (initialValue) {
// 提供初值,accumulator 取值为 initialValue
accumulator = initialValue
} else {
// 在没有初始值的空数组上调用 reduce 将报错。
if (O.length === 0) {
throw new TypeError('Reduce of empty array with no initial value');
}
// 如果指定的属性在指定的对象或其原型链中,则 in 运算符返回 true
// 循环判断当 O 及其原型链上存在属性 k 时开始
while (k < O.length && !(k in O)) {
k++;
}
// 没有提供初值, `accumulator`取数组中的**第一个值**
accumulator = O[k++]
}
while (k < O.length) {
if (k in O) {
let currentValue = O[k]
accumulator = callback(accumulator, currentValue, k, O)
}
k++
}
return accumulator
}
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
const array2 = [{label: '十', num: 10}, {label: '八', num: 8}];
const reducer2 = (acc, cur) => {
return {
label: `${acc.label} ${cur.label}`,
num: acc.num + cur.num
}
}
// 1 + 2 + 3 + 4
console.log(array1.myReduce(reducer));
// expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.myReduce(reducer, 5));
// expected output: 15
console.log(array2.myReduce(reducer2, {label: '一', num: 0}));
复制代码
另外向大家着重推荐下另一个系列的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列 记得点赞哈
今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦 点击此处交个朋友
Or 搜索我的微信号infinity_9368
,可以聊天说地
加我暗号 “天王盖地虎” 下一句的英文
,验证消息请发给我
presious tower shock the rever monster
,我看到就通过,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧