前言
书接上文,在上次我手写了部分JavaScript的方法之后,还是感觉意犹未尽,于是决定将剩下的数组方法也实现掉。
手写every方法 🛰🛰
我们知道ervery方法的特殊之处在于它的返回值是一个布尔值,并且every方法的特点方法会遍历数组的每一项,如果有有一项不满足条件,则表达式返回false,剩余的项将不会再执行检测;如果遍历完数组后,每一项都符合条,则返回true。
那么下我们来实现every方法
Array.prototype.myEvery = function (cb) { var _arr = this; var len = _arr.length; var arr2 = arguments[1] || window; var _res = true; for (var i = 0; i < len; i++) { if (!cb.apply(arr2, [_arr[i], i, _arr])) { _res = false; break; } } return _res; };
我们主要来关注for循环的部分,在if条件中cb可以通过apply方法来更改this的指向,并且对函数的返回值进行判断,如果有一项返回值为fasle,那么就给变量_res赋值为false,break循环,最后将 _res给return出去。
实例数据:
let arr = [ { name: "张三", age: 21, }, { name: "李四", age: 24, }, { name: "王五", age: 31, }, ];
实际使用:
let res = arr.myEvery(function (item, index, arr) { console.log(item); return item.age > 30; }); console.log(res); console.log("-----------------") let res2 =arr.every(function (item, index, arr) { console.log(item); return item.age > 30; }); console.log(res2);
因为数组在执行到第一项时就不满足条件,所以返回值为fasle,并且终止循环。
手写some方法🍌🍌
smoe方法与every方法类似都是返回布尔值,不同点就是some是只要有一个符合条件就会返回true,不需要数组中的每一项都满足条件。他们两者的实现逻辑和思路是类似的
Array.prototype.mySome = function (cb) { var _arr = this; var len = _arr.length; var arr2 = arguments[1] || window; var _res = false; for (var i = 0; i < len; i++) { if (cb.apply(arr2, [_arr[i], i, _arr])) { _res = true; break; } } return _res; };
我们看一下代码就不难发现,其实就是判断的条件略微改动了一下,如果返回值是true,那么就给_res赋值为true,然后break循环,最后将 _res给return出去。这样就达到了目的
具体使用:
let res3 = arr.some(function (item, index, arr) { console.log(item); return item.age > 30; }); console.log(res3); console.log("---------------"); let res4 = arr.mySome(function (item, index, arr) { console.log(item); return item.age > 30; }); console.log(res4);
手写reduce方法 🌲🌲
重头戏来了,reduce方法是这些方法中我认为最特殊的一个,首先在我们平时使用的时候,reduce就是一个比较迷的存在,那么这次我们就彻底的搞懂reduce方法
什么是reduce方法
reduce 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值
reduce方法可以接受两个参数:回调函数,函数迭代的初始值(非必传)
案例解释
我们可以从下面的代码来理解
let array = [1, 2, 3, 4]; let arr4 = array.reduce((prev, cur, index, arr) => { console.log(prev, cur, index); return prev + cur; }); console.log(arr4);
这里我们来分析一下这里打印的第一行中prev为1,也就意味着当们当不传递第二个参数的时候,prev默认为数组的第一个元素即array[0],然后此时的cur为array[1],index为1,然后在第二行中3,代表着上一轮的prev+cur也就是3, 然后这个cur也就变成了3,当前的index就是2,以此类推。
最终的结果就是返回这些元素之和也就是10
那么如果传入第二个参数呢?
let array = [1, 2, 3, 4]; let arr4 = array.reduce((prev, cur, index, arr) => { console.log(prev, cur, index); return prev + cur; },0); console.log(arr4);
可以发现这次执行了4次,那是因为这次cur是从1开始,并且prev一开始的值为0,index的值是0
清楚了以上以后我们开始来实现reduce方法
实现部分
Array.prototype.myReduce = function (cb, initialValue) { var _arr = this; var len = _arr.length; var _item; var i = 0; if (typeof cb != "function") { throw new Error("传入的第一个参数需要是函数"); } // 当没有传递initialValue的时候默认为数组的第0项 if (initialValue == undefined) { i = 1; initialValue = _arr[0]; } for (i; i < len; i++) { _item = deepClone(_arr[i]); initialValue = cb(initialValue, _item, i, _arr); } return initialValue; };
在这个函数中接收两个参数,cb是一个回调函数,还有函数迭代的初始值(可以不传)
思路:
其实实现的逻辑也不难,首先判断一下cb是否为函数类型,如果不是函数类型那么就抛出一个错误,然后在判断是否传入了initialValue
如果没有传递,那么给i赋值为1,这样for循环的时候就从索引为1开始执行。并且给initialValue赋值为数组的第一个元素arr[0],
然后就进行for循环 ,_item被赋值为arr[1] 因为这个方法不能改变this的指向,所以不需要使用apply,调用回到函数cb,传递四个参数,initialValue就相当于是prev , _item相当于是cur,然后返回值还是initialValue,然后再次执行,将initialValue值传入函数中。当最终结束的时候将initialValue返回
总结🤙🤙
通过对这几个常用的数组方法的书写,使自己更加深刻的认知了JavaScript,并且也认识到平时在学习的时候应该多思考多钻研,要有一种探究的精神,这样才可以一点一点提高。