JavaScript之手撕常用数组高阶函数,30分钟轻松入门flutter

29 阅读2分钟
  • 接受一个函数或者多个函数作为参数

  • 输出一个函数

JavaScript中的高阶函数大多都是接受一个函数作为参数,具体传参如下:

Array.prototype.func = function(callback(currentValue[, index[, array]]){

}[, thisArg])

  • callback:对数组元素进行操作的回调函数

  • currentValue:正在处理的当前元素

  • 当前元素的索引

  • 调用高阶函数的数组

  • thisArg:可选,执行callback函数时绑定的this

forEach


用法

forEach主要用于数组的简单遍历,基本使用如下

arr = [1, 2, 3, 4]

arr.forEach((val, index) => {

console.log(val, index)

})

// 相当于原来的for循环

for (var i = 0; i<arr.length; i++) {

console.log(arr[i], i)

}

模拟实现

  • 判断调用函数的this是否合法

  • 判断传入的回调函数是否合法

  • 模拟具体功能

Array.prototype.myForEach = function (callbackFn) {

// 判断this是否合法

if (this === null || this === undefined) {

throw new TypeError("Cannot read property 'myForEach' of null");

}

// 判断callbackFn是否合法

if (Object.prototype.toString.call(callbackFn) !== "[object Function]") {

throw new TypeError(callbackFn + ' is not a function')

}

// 取到执行方法的数组对象和传入的this对象

var _arr = this, thisArg = arguments[1] || window;

for (var i = 0; i<_arr.length; i++) {

// 执行回调函数

callbackFn.call(thisArg, _arr[i], i, _arr);

}

}

map


用法

map函数对数组的每个元素执行回调函数,并返回含有运算结果的新数组,基本使用如下:

const users = [

{ name: 'John', age: 34 },

{ name: 'Amy', age: 20 },

{ name: 'camperCat', age: 10 }

];

// 需求:取出users所有人的name,并存放在新数组中

// 不使用map

names = []

for (var i = 0; i<users.length; i++){

names.push(users[i].name)

}

// map是对数组的每一个元素进行操作,因此上述代码可以使用map来进行简化

names = users.map(function (user) {

return user.name

})

// 如果学过箭头函数,还可以进一步简化

names = user.map(user => user.name)

模拟实现

有了上面forEach的编写经验,map只需要稍作修改,使其结果返回新的数组(这里省略掉异常判断)。

Array.prototype.myMap = function(callbackFn) {

var _arr = this, thisArg = arguments[1] || window, res = [];

for (var i = 0; i<_arr.length; i++) {

// 存储运算结果

res.push(callbackFn.call(thisArg, _arr[i], i, _arr));

}

return res;

}

filter


用法

filter是过滤的意思,它对数组每个元素执行回调函数,返回回调函数执行结果为true的元素。

// 返回偶数

arr = [1, 2, 3, 4, 5];

arr.filter(val => val % 2 == 0)

模拟实现

map的实现大同小异,map返回执行回调后所有的元素,而filter只返回执行结果为true的元素。

Array.prototype.myFilter = function(callbackFn) {

var _arr = this, thisArg = arguments[1] || window, res = [];

for (var i = 0; i<_arr.length; i++) {

// 回调函数执行为true

if (callbackFn.call(thisArg, _arr[i], i, _arr)) {

res.push(_arr[i]);

}

}

return res;

}

every


用法

every并不返回数组,返回布尔值true/false,数组的每个元素执行回调函数,如果执行结果全为trueevery返回true,否则返回false

arr = [1, 3, 5, 7, 8, 9]

// false,8为偶数,不满足

arr.every(ele => ele % 2 == 1)

arr2 = [2, 4, 6]

// true 都是偶数

arr2.every(ele => ele % 2 == 0)

模拟实现

Array.prototype.myEvery = function(callbackFn) {

var _arr = this, thisArg = arguments[1] || window;

// 开始标识值为true

// 遇到回调返回false,直接返回false

// 如果循环执行完毕,意味着所有回调返回值为true,最终结果为true

var flag = true;

for (var i = 0; i<_arr.length; i++) {

// 回调函数执行为false,函数中断

if (!callbackFn.call(thisArg, _arr[i], i, _arr)) {

return false;

}

}

return flag;

}

some


用法

someevery功能类似,都是返回布尔值。只要回调函数结果有一个truesome便返回true,否则返回false

模拟实现

Array.prototype.mySome = function(callbackFn) {

var _arr = this, thisArg = arguments[1] || window;

// 开始标识值为false

// 遇到回调返回true,直接返回true

// 如果循环执行完毕,意味着所有回调返回值为false,最终结果为false

var flag = false;

for (var i = 0; i<_arr.length; i++) {

// 回调函数执行为false,函数中断

if (callbackFn.call(thisArg, _arr[i], i, _arr)) {

return true;

}

}

return flag;

}

find/findIndex


用法

findfindIndexES6新添加的数组方法,返回满足回调函数的第一个数组元素/数组元素索引。当数组中没有能满足回调函数的元素时,会分别返回undefined和-1

const users = [

{ name: 'John', age: 34 },

{ name: 'Amy', age: 20 },

{ name: 'camperCat', age: 10 }

];

  1. 返回name为John的年龄

在没有find方法时,实现类似效果,需要循环遍历,查找到name=Jonn后,找到年龄。但使用find就可以轻松快捷的实现。

JohnAge = users.find(user => user.name === 'John').age

  1. 返回name为Amy的索引

ES6以前Array提供了查找数组中元素的方法:indexOf,lastIndexOf,但是这两个方法在查找对象时都无能为力。

// 返回值为-1,说明未查到Amy

users.indexOf({ name: 'Amy', age: 20 })

// 返回hi为1,成功查到Amy

users.findIndex(user => user.name === 'Amy')

indexOf虽然可以用来查找基本类型的元素索引,但其语义化并不好,每次需要与-1进行比较,因此ES6添加了新的includes方法。

模拟实现

find/findIndex都是寻找到第一个满足回调函数的元素返回,上面我们学习的some也是类似机制,因此它们的原生代码类似。

Array.prototype.myFind = function(callbackFn) {

var _arr = this, thisArg = arguments[1] || window;

// 遇到回调返回true,直接返回该数组元素

// 如果循环执行完毕,意味着所有回调返回值为false,最终结果为undefined

for (var i = 0; i<_arr.length; i++) {

// 回调函数执行为false,函数中断

if (callbackFn.call(thisArg, _arr[i], i, _arr)) {

return _arr[i];

学习分享,共勉

题外话,毕竟我工作多年,深知技术改革和创新的方向,Flutter作为跨平台开发技术、Flutter以其美观、快速、高效、开放等优势迅速俘获人心

开源分享:docs.qq.com/doc/DSmRnRG…