这套题还不错,感兴趣的猿可以试一试:前端开发工程师

甚么是高阶函数?
甚么是函数柯里化?
甚么又是compose函数?
概念:

  1. 接收一个函数或者多个函数作为参数的函数,如js中自带的map some every filter reduc
  2. 函数执行返回一个函数,如bind

以上只要满足一条都称之为高阶函数. 柯里化函数、组合函数统称为高阶函数
接下来看一些js自带的高阶函数栗子:

// map 接收一个函数 数组中的每一项都会执行这个方法
// 返回一个新数组 数组的元素由原数组的每一项执行接收函数处理后的值
const arr = [1,5,6,44,99,36,77];
const res = arr.map(item => item + 1);
// 原数组每一项调用函数处理后返回的 新数组
console.log(res) // [2, 6, 7, 45, 100, 37, 78]

//手动实现一下(实现了大致基本的功能并不完善)
Array.prototype.myMap = function(fn){
    const len = this.length;
    const newArr = [];
    for(let i = 0;i < len;i++){
        // 原数组的每一项执行fn函数处理后的值push到新数组中
        newArr.push(fn(this[i]))
    }
    return newArr
}
const res = arr.myMap(item => item + 1)
console.log(res);  //[2, 6, 7, 45, 100, 37, 78]

// filter 返回原数组中符合条件的元素并返回,如果没有符合条件的返回空数组
const res = arr.filter(item => item > 20) // [44, 99, 36, 77]

// 手动实现一下(实现了大致基本的功能并不完善)
Array.prototype.myFilter = function(fn){
    const len = this.length;
    let newArr = [];
    for(let i = 0; i < len;i++){
        // 判断fn函数执行后返回 值为true的当前项push到新数组中
        fn(this[i]) && newArr.push(this[i])
    }
    return newArr
}

const r = arr.myFilter(item => item > 20)
console.log(r);  // [44, 99, 36, 77]
 

柯里化函数

直接上代码:

// 看一个简单的栗子
const res = add(1,2)(3);
console.log(res) // 6

//解析: add 函数传入参数执行后返回一个函数再次传入参数再次执行 然后求和

// 实现
const add = (...params)=>{
    // add 函数执行返回一个新函数
    // 因为大函数执行返回的小函数还要被执行一次所以形成了临时闭包 上下文暂时不被释放
    // 利用临时 闭包将params参数预存储起来
    return (...args) => {
        // 将params args 拼接求和
        params = params.concat(args)
        return params.reduce((result,item) => result + item)
    }
}
 

得到结论:利用闭包保存的作用,把一些信息预先存储起来,[预处理],供其下级上下文中后期使用。我们把这种预先存储/预先处理的机制称之为 ------函数柯里化

柯里化函数的高阶应用:

// 看一个复杂的栗子
let add = curring()
let res = add(1)(2)(3);
console.log(+res); //6

add = curring()
res = add(1,2,3)(4);
console.log(+res); //10

add = curring()
res = add(1)(2)(3)(4)(5);
console.log(+res); //15

// 解析:和之前简单的栗子不同点 上例中add 函数固定调用了两次 现在我们不能确定会调用多少次

// 实现:
const  curring = () => {
    // 在闭包中创建一个params集合用来预存储每次add执行所接收的实参
    let parmas = [];
    const add = (...args) => {
        parmas = parmas.concat(args)
        // 这里返回add 函数 因为我们不确定add函数执行完会调用多少次、每执行一次 接着返回一个add函数供其下次执行
        return add
    }
    // 将一个对象 转化为字符串或者数字 优先级[Symbol.toPrimitive] > valueOf >toString > Number
    // 基于重构转化为字符串的过程 实现求和操作
    add[Symbol.toPrimitive] = () => {
        // 将预先存储的 params 进行求和
        return parmas.reduce((result,item) => result + item)
    }
    return add
}
 

componse 函数

函数式编程中有一个很重要的概念: 函数组合 把处理的函数像管道一样连接起来,然后数据通过这个管道得到最终的结果
代码:

const fn1 = x => x + 1;
const fn2 = x => x * 2;
const fn3 = x => x + 10;
console.log(fn3(fn1(fn2(1))));

// 解析: 首先执行 fn2 传入参数1 返回 fn2的执行结果 1*2,再将fn2 的结果传入fn1 以此类推... 
// 得到最终结果13
// 如果有fn 99999 呢 这样显然可读性太差,这样就需要我们的组合函数了

// 思考:我们知道将一个或多个函数作为参数的函数称为高阶函数 那是不是可以将fn1 fn2 fn3 传入到一个组合函数中处理 再将结果累加并返回呢?

// 实现:
const compose = function compose(...fns){
    // x 为compose 第一次执行完 小函数的参数 初始值
    return function operate(x){
        //循环compose 实参 函数列表
        // result 为上一次函数执行返回的结果
        // item 为当前循环到的函数
        // reduce 从左到右迭代 reduceRight从右到左
        return fns.reduceRight((result,item)=>{
            // 将当前函数执行的结果返回给result
            return item(result)
        },x)
    }
}
const res = compose(fn3,fn1,fn2)(1);
// compose 函数执行一次 再传入参数执行
// compose 函数需要返回一个函数
console.log(res);