以下题目来自掘金等其它博客,但是问题的答案都是根据笔者自己的理解做出的。如果你最近想要换工作或者巩固一下自己的前端知识基础,不妨和我一起参与到每日刷题的过程中来,如何?
第六天要刷的手写题如下:
- 实现Array.prototype.map
- 实现Array.prototype.reduce
- 实现Array.prototype.reduceRight
- 实现Array.prototype.filter
下面是我自己写的答案:
1. 实现Array.prototype.map
首先必须要明白map函数的执行原理:
- 遍历原始数组:对于调用 map() 方法的数组,会遍历每个元素。
- 对每个元素应用回调函数:对于每个元素,都会调用传递给 map() 方法的回调函数,并传入三个参数:当前元素的值、当前元素的索引和原始数组本身。回调函数用来对每个元素进行处理。
- 构建新数组:将回调函数返回的结果存储在新的数组中。这些结果按照原始数组的顺序排列,构成了新数组。
- 返回新数组:当遍历完所有元素并处理完成后,map() 方法返回包含处理结果的新数组。
javascript
function myMap (cb) {
if(!Array.isArray(this)) throw new Error('must be called by array');
const _stack = [...this];
const _result = [];
while (_stack.length) {
const _v = _stack.pop();
const _tmp = cb(_v, _stack.length-1, _stack);
// do some your judgement
_result.push(_tmp);
}
return _result;
}
2. 实现Array.prototype.reduce
首先必须要明白reduce函数的执行原理:
- 初始化累加器:首先,将累加器(accumulator)的初始值设置为指定的初始值(或者默认为数组的第一个元素,如果没有提供初始值)。
- 遍历数组元素:从数组的第一个元素开始,逐个遍历每个元素。
- 应用回调函数:对于每个元素,都会调用传递给 reduce() 方法的回调函数,并传入四个参数:累加器、当前元素的值、当前元素的索引和原始数组本身。回调函数用来根据当前元素的值和累加器的值进行计算,并返回新的累加器值。
- 更新累加器:将回调函数返回的新累加器值,作为下一次迭代的累加器值。
- 返回最终结果:当遍历完所有元素后,reduce() 方法返回最终的累加器值作为计算结果。
javascript
function myReduce (cb, initialValue) {
if(!Array.isArray(this)) throw new Error('must be called by array');
let _acc = initialValue ?? this[0];
const startIndex = Number(initialValue === undefined);
for (let i = startIndex; i < this.length; i++) {
_acc = cb(_acc, this[i], i , this);
}
return _acc;
}
- !!需要注意的是cb需要四个形参,这四个参数分别表示的含义为:归并值、当前值、当前序列号、数组本组。
- !!需要注意的是起始位置startIndex会随着initialValue的存在而改变,如果存在则从0开始,否则将第一个元素作为initialValue并且从序列号为1开始。
3. 实现Array.prototype.reduceRight
首先必须要明白reduceRight函数的执行原理:
- 初始化累加器:首先,将累加器(accumulator)的初始值设置为指定的初始值(或者默认为数组的最后一个元素,如果没有提供初始值)。
- 逆向遍历数组元素:从数组的最后一个元素开始,逐个逆向遍历每个元素。
- 应用回调函数:对于每个元素,都会调用传递给 reduceRight() 方法的回调函数,并传入四个参数:累加器、当前元素的值、当前元素的索引和原始数组本身。回调函数用来根据当前元素的值和累加器的值进行计算,并返回新的累加器值。
- 更新累加器:将回调函数返回的新累加器值,作为下一次迭代的累加器值。
- 返回最终结果:当逆向遍历完所有元素后,reduceRight() 方法返回最终的累加器值作为计算结果。
javascript
function myReduce (cb, initialValue) {
if(!Array.isArray(this)) throw new Error('must be called by array');
let _acc = initialValue ?? this.at(-1);
const startIndex = initialValue ? this.length -1 : this.length -2;
for (let i = startIndex; i > 0; i--) {
_acc = cb(_acc, this[i], i , this);
}
return _acc;
}
!!reduceRight和reduce的区别在于:遍历数组的方向不同,啊这样的话为什么不先把数组翻转过来呢?
4. 实现Array.prototype.filter
首先必须要明白filter函数的执行原理:
- 创建一个空数组(称为结果数组)来存储满足条件的元素。
- 遍历原始数组中的每个元素。
- 对于每个元素,调用传递给 filter() 方法的回调函数,并将当前元素作为参数传递给回调函数。
- 回调函数根据设定的条件对当前元素进行评估。如果回调函数返回 true,则表示当前元素满足条件,将其添加到结果数组中。
- 继续遍历原始数组中的下一个元素,并重复步骤 3 和 4,直到遍历完所有元素。
- 返回结果数组,其中包含满足条件的元素。
javascript
function myFilter (cb) {
if(!Array.isArray(this)) throw new Error('must be called by array');
const _stack = [...this];
const _result = [];
while (_stack.length) {
const _v = _stack.pop();
if (cb(_v, _stack.length-1, _stack) === true) {
_result.push(_v);
}
}
return _result;
}
!!注意: 需要写成:if (cb(_v, _stack.length-1, _stack) === true)
而不是if (cb(_v, _stack.length-1, _stack))