闭包进阶之:柯里化函数

161 阅读3分钟

「这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战」。

闭包进阶之:柯里化函数

  • 迭代方法:forEach map reduce reduceRight find findIndex filter some exery... MDN
  • reduce数组的迭代方法,它支持结果的累积,因为在下一轮迭代可以拿到上一轮迭代的返回结果
let arr = [1, 2, 3, 4]
let total = arr.reduce((result, item, index) => {
  // 数组从第二项开始迭代
  // 第一轮 result数组第一项1 item数组第二项2 index是第二项的索引1
  // 第二轮 result存储的是上一轮返回的结果3  item=3 index=2
  // 第三轮 result=6 item=4 index=3 

  return result + item
})

let total = arr.reduce((result, item) => {
  // 传递的第二项是给result设置的初始值   item从数组的第一项开始迭代
  return result + item 
},0)
  • 柯里化函数思想

预先存储(预处理),利用闭包的"保存机制",我们把一些值事先存储起来,供其下级上下文中后期使用.

const fn = (...params) => {
  return (...arg) => {
    params = params.concat(arg)
    return params.reduce((result, item) => result + item)
  }
}
let res = f(1,2)(3)
console.log(res) //6   1+2+3=6

基于console.log或alert输出一个函数:会默认先把函数转化为了字符串[Symbol.toPrimitive -> valueOf -> toString],然后再输出[只不过浏览器为了让开发者知道这是个函数字符串,所以在输出的字符串前面,加了一个"f"]

const fn = function(){
  // ...
}
fn[Symbol.toPrimitive] = function () {
  console.log('ok')
  return 'zhufeng'
}
console.log(fn)

// 函数柯里化后的求和
const curring = function curring(){
  let params = []
  const add = (...args) => {
    params = params.concat(args)
    return add
  }
  add[Symbol.toPrimitive] = () => params.reduce((result, item) => result + item)
  return add
}

let add = curring()

let res = add(1)(2)(3)

console.log(res) // 6
  • lodash中的柯里化函数
    • 功能:创建一个函数,该函数接受一个或者多个func的参数,如果func所需要的参数都被提供则执行func并返回执行的结果.否则继续返回该函数并等待接收剩余的参数.
    • 参数: 需要柯里化的函数
    • 返回值: 柯里化后的函数
    const _ = require('lodash')
    
    function getSum(a, b, c){
      return a + b + c
    }
    const curried = _.curry(getSum)
    let curried1 = curried(1, 2)
    console.log(curried1(7))
    
    • 原理实现
    function curry (func){
      return function curriedFn(...args){
        //判断传入的参数 与传入的函数的形参个数是否相同
        if(args.lenght < func.length){
          return function(){
            return curriedFn(...args,...arguments)
          }
        }
        return func(...args)
      }
    }
    
  • 函数组合及其实现
// 在函数式编程当中有一个很重要的概念就是函数组合, 实际上就是把处理数据的函数像管道一样连接起来, 然后让数据穿过管道得到最终的结果。 例如:
    const add1 = (x) => x + 1;
    const mul3 = (x) => x * 3;
    const div2 = (x) => x / 2;
    div2(mul3(add1(add1(0)))); //=>3

    // 而这样的写法可读性明显太差了,我们可以构建一个compose函数,它接受任意多个函数作为参数(这些函数都只接受一个参数),然后compose返回的也是一个函数,达到以下的效果:
    const operate = compose(div2, mul3, add1, add1)
    operate(0) //=>相当于div2(mul3(add1(add1(0)))) 
    operate(2) //=>相当于div2(mul3(add1(add1(2))))

    // 简而言之:compose可以把类似于f(g(h(x)))这种写法简化成compose(f, g, h)(x),请你完成 compose函数的编写 
    const compose = function compose(...funcs){
      let len = funcs.length
      if (len === 0) return x => x
      if (len === 1) return funcs[0]
      return function operate(x){
        return funcs.reduceRight((result, func) => {
          return func(result)
        },x)
      }
    }
    // 思考:redux中的compose函数编写思想
    /* function compose(...funcs) {
        if (funcs.length === 0) {
            return (arg) => arg
        }
        if (funcs.length === 1) {
            return funcs[0]
        }
        return funcs.reduce((a, b) => (...args) => a(b(...args)))
    } */