手写柯里化,实现柯里化

柯里化,就是将接受多个参数的函数变换成接受一个单一参数的函数。

闭包的应用场景就是函数科里化。(延长变量的生命周期)

参数复用,利用闭包将函数的参数储存起来,等参数达到一定数量时执行函数

 

fn(x, y) -> fn(x)(y)

上面的代码就是把fn函数做成嵌套函数,外层函数的返回值是内层函数。外层函数调用完之后,能接着调用。

涉及到的概念,高阶函数,闭包,call/apply,argument。

科里化执行函数的核心是:有参数传入时,收集参数,返回函数;收集参数完毕,执行,返回值。

 

第一种方法:比较容易理解

fn指的是源处理函数,如sum,currArgs 是调用curry时传入的参数列表,比如(1,2)(3)

复制代码
function curry(fn, currArgs){return function(){
        let args =  Array.from(arguments);
        // 首次调用的时候,若未提供最后一个参数currArgs,则不用进行args拼接
        if(currArgs !== undefined){
            args = args.concat(currArgs)
        }
        // 递归调用,判断args的个数,是否与fn的参数相对能,相等了就可以把参数都传给fn,进而输出;否则继续递归调用,一直到两者相等。
        if(args.length < fn.length){  // fn.length 是fn函数参数的个数
            return curry(fn, args);
        }
        return fn.apply(null, args);
    }
}
function sum(a, b, c) {
    console.log(a + b + c);
}

const fn = curry(sum);

fn(1, 2, 3); // 6
fn(1, 2)(3); // 6
复制代码

 

  第二种方法,

复制代码
const curry = (fn) => {
    if (typeof fn !== 'function') {
        console.log('function')
      throw Error('No function provided')
    }

    return function curriedFn (...args) {
        // 括号里扩展运算符的作用,是把传过来的参数变成数组。
        // 等同于 args = Array.from(arguments);

      if (fn.length > args.length) {  // 未达到触发条件,继续收集参数
        return function () {
            /**
             * [].slice.call(arguments) 将类数组转化为数组,
             * 上一行代码的原理是call会将slice方法内部的this就会被替换成arguments,
             * 并循环遍历arguments,复制到新数组返回,这样就得到了一个复制arguments类数组的数组对象。
             * 等同 Array.from(arguments)
             * 也等同于 Array.prototype.slice.call(arguments)
             */
          return curriedFn.apply(null, args.concat(Array.from(arguments)))
        }
      }
    //   apply:方法能劫持另外一个对象的方法,继承另外一个对象的属性.
    // Function.apply(obj,args)方法能接收两个参数
    // obj:这个对象将代替Function类里this对象
    // args:这个是数组,它将作为参数传给Function(args-->arguments)       
      return fn.apply(null, args)
    //   args作为参数,被fn调用。
    }
  }

  const multiply = (x, y, z) => x*y*z;
  const curryMul = curry(multiply);
  const result = curryMul(1)(2)(3); // 1*2*3 = 6
  console.log('result',result)
posted @ 2023-04-10 01:25  m2maomao  阅读(87)  评论(0编辑  收藏  举报