手写Promise01-高阶函数和函数柯里化

138 阅读2分钟

高阶函数的概念, 以下两个条件满足任何一个都是高阶函数

  1. 一个函数返回一个函数
  2. 一个函数可以接受一个函数 高阶函数
function fn(){
    cb()
}

高阶函数的使用

假设我们现在有一个需求,我们需要给函数添加一些额外的逻辑,但是并不改变核心的代码

function core(){
    console.log('core')
}
Function.prototype.before=function(cb){
    return ()=>{
        cb()
        this()
    }
}
let newCore=core.before(()=>{
    console.log('before')
})
newCore()

运用高阶函数我们就可以实现这个效果

闭包的概念

什么叫闭包? 函数的定义是有作用域的概念的,一个函数的作用域和执行的作用域不在同一个,那么就会出现闭包

函数柯里化

函数柯里化 多个参数的传入 把它转化成n个函数,这样写的好处就是可以暂存变量。函数柯里化可以解决闭包内存溢出的问题。一般柯里化要求都是一个个的传。这种函数我们叫做偏函数,柯里化是一种定参的规范

function fn(a){
    return function a(b){
        return function b(){
        }
    }
}
fn(a,b,c)
let fn1=fn(a)
let fn2=fn1(b)
let xxx=fn2(b)

函数柯里化场景

判断变量类型

typeof 一般用来判断基础类型。 除了这个以外,我们用的比较多的还有instanceof 也可以通过原型的toString方法来放回原型的具体类型Object.prototype.toString.call()

function isType(val,typing){
    return Object.prototype.toString.call(val)==`[object ${typing}]`
}
console.log(isType(null,'String'))

修改上面这个函数,让他的作用域变得更加大一点

function isString(typing){
    return function(val){
        return Object.prototype.toString.call(val)==`[object ${typing}]`
    }
}
let myIsString=isString('String')
myIsString('abc')
myIsString(123)

我们每次执行都可以传入剩余的这些参数。可以通过上面这种写法实现一个通用的柯里化函数.可能还会存在参数个数未知的柯里化。但是一般碰到的函数柯里化参数个数都是已知的。如果碰到未知的柯里化函数问题。我们可以考虑递归处理该函数

function curring(){
    const inner=(args=[])=>{
     return args.length=>fn.length?fn(...args):(...userArgs)=>inner([...args,...userArgs])
    } // 递归返回函数
    return inner()
}

function sum(a,b,c,d){
    return a+b+c+d
}
let sum1=currying(sum)
let sum2=sum1(1)
let sum3=sum(2,3)
let result=sum3(3,4)
console.log(result)

但是要记住一个问题,那就是sum只有4个参数。你如果定义一个sum4再传入一个5就会报错。处分你对sum进行修改

function sum(...args){
    return [...args].reduce((a,b)=>{return a+b},0)
}

再次修改上方的类型判断函数,让他更加符合正常代码编写的柯里化入参规范

function isType(typing,val){
    return Object.prototype.call(val)==`[object ${typing}]`
}
let isString=curring(isType)('String')
console.log(isString('abc'))
let isNumber=curring(isType)('isString')
console.log(isNumber('abc'))

封装一个工具类,扩展判断变量类型方法

function isType(typing,val){
    return Object.prototype.toString.call(val)==`[object ${typing}]` 
}
let util={}
['String','Number','Boolean','Null','Undefined'].forEach((element)=>{
        util['is'+element]=curring(isType)(element)
})
console.log(util.isString('abc'))

8行封装了一个变量类型判断方法。用户也不用再去传递对应的变量类型,直接调用函数方法