上一章简单的创建了些函数并执行了函数,然后自己封装了一个forEach的API,我们给这个forEach传了一个特别的参数,他是一个函数。那么这个forEach其实就是一个高阶函数。
1.数据类型
js的数据类型目前看来就是八种:常见的Nmber,String,Boolean,null,undefined,Object,加上ES6新增的symbol,还有个ES11加的BigInt。其中Object我们称为引用数据类型或者复杂数据类型,他是一个大类,object,fuction,array,date...都属于Object
1.1传递函数:
自己写一个函数试试:判断参数的数据类型
const confirmType=(arg)=>{
console.log(typeof arg);
}
const data=1
confirmType(data)
我们把它给稍微改一下后
const dataFn=()=>{
console.log("这是函数");
}
const confirmType=(arg)=>{
if(typeof arg==="function")
arg()
else
console.log("不是函数,是"+ typeof arg);
}
confirmType(dataFn)
confirmType(1)
//这是函数
//不是函数,是number
1.2 返回函数
上面的例子我们是把一个函数传递给另一个函数,现在我们再写一个函数返回另一个函数。
let crazy=()=>String
console.log(crazy()("11111"));
crazy返回了一个String函数,但是只返回没有执行。
我们上面铺垫这么多是为了引入高阶函数的定义:高阶函数是接收函数作为参数,或者返回函数作为输出的函数。
2.抽象和高阶函数
首先我们需要知道什么是抽象。我觉得下面这个文章说的挺好的:
抽象让我们专注于预定的目标,而不必关心底层的系统概念。
2.1通过高阶函数实现抽象
比如我们之前封装的API forEach,就是函数抽象出了遍历数组的问题。当你使用它时,不需要理解它怎么遍历的。
我们再来写一个遍历对象的高阶函数:
const forEachObject=(obj,fn)=>{
for(let key in obj){
if(obj.hasOwnProperty(key)){
fn(key,obj[key])
}
}
}
const obj={a:1,b:2}
forEachObject(obj,(k,v)=>console.log(k+":"+v))
//a:1
//b:2
2.2控制流程处理
我们简单的创建一个unless函数,接收一个断言,如果是false就调用fn
查找偶数:
const forEach=(array,fn)=>{
for(let i=0;i<array.length;i++){
fn(array[i])
}
}
const unless=(boo,fn)=>{
if(!boo) fn()
}
forEach([1,2,3,4,5],(number)=>{
unless((number%2),()=>{
console.log(number);
})
})
//2 4
3.实用的高阶函数
上面都是我们自己封装的高阶函数,现在我们来讨论一些真实的高阶函数:
3.1 every函数
他接受两个参数,一个数组和一个函数
const every=(arr,fn)=>{
let result =true
for(let i=0;i<arr.length;i++){
result=result&&fn(arr[i])
}
return result
}
every([NaN,NaN,NaN],isNaN) //ture
every([NaN,NaN,4],isNaN) //false
//用 for ... of 循环重写every
const every1=(arr,fn)=>{
let result =true
for(const v of arr)
result=result&&fn(v)
return result
}
3.2 some函数
some函数和every函数基本一样,只是给定的result初始值有区别,some给定的是false,同时将&&换成||
3.3 sort函数
sort是Array原型的内置函数。
arr.sort([compareFn])这里的compareFn是可选的,如果我们不提供compareFn,元素将会被转化为字符串并按照Unicode编码点顺序排序。在编写compareFn之前我们先实现一下逻辑:
Array.prototype.sort() - JavaScript | MDN
function compareFn(a, b) {
if (在某些排序规则中,a 小于 b) {
return -1;
}
if (在这一排序规则下,a 大于 b) {
return 1;
}
// a 一定等于 b
return 0;
}
我们在看完Mdn上面的compareFn的算法后,我们自己尝试去用一个函数返回的值去入参。
const sortBy=(v)=>{
return (a,b)=>{
let result =(a[v]<b[a])?-1:(a[v]>b[v])?1:0
return result
}
}
sortBy接受一个参数v并返回一个函数接受两个参数。我们这时候就需要注意一下,这个返回的函数如何让得来?这里就用到了闭包,下一章我们将介绍闭包,闭包和高阶函数。