函数式编程之柯里化(curry)

293 阅读2分钟

定义

科里化函数:固定某个函数的一些参数,得到该函数剩余参数的一个新函数,如果没有剩余参数,则调用

function add(x, y, z) {
    return (x + y) * z;
 }

add(2,3,1)
add(2,4,9)
add(2,6,3)
add(2,2,1)
add(2,2,3)
  • 会发现在调用时第一个参数是一致的都是2,那么就可以使用curry将2固定,产生一个新的函数

柯里化的实现

    //在函数式编程中,科里化最重要的作用是把多参函数变为单参函数
    function curry (fun) {
        let _this = this
        let args = Array.prototype.slice.call(arguments,1)
        return function () {
            // arguments转为数组
            let curArgs = Array.from(arguments)
            let totalArgs = args.concat(cruArgs)
            if (totalArgs.length >= fun.length) {
                fun.apply(null,totalArgs)
            }else {
                totalArgs.unshift(fun)
                curry.apply(_this,totalArgs)
            }

        }
    }
    

Array.from()  静态方法从可迭代类数组对象创建一个新的浅拷贝的数组实例。

  • 有了curry方法之后
let curryAdd1 = curry(add,2)

//add(2,3,1)
curryAdd1(3,1)

//add(2,4,9)
curryAdd1(4,9)

let curryAdd2 = curry(curryAdd1,2)

//add(2,2,1)
curryAdd2(1)

//add(2,2,3)
curryAdd2(3)
    

柯里化中的this指向问题

  • this问题

var name = "window";

function fun(a, b) {
  console.log(this.name,1,2);
}

var obj = {
  name: "obj",
  fun,
};

var funCarry1 =curry(fun, 1)
var funCarry2 = curry(obj.fun, 1);

funCarry1("全局调用") // 输出 window, 1, wendow调用
funCarry2("obj调用") //  输出 wnndow, 1, obj调用

会发现 funCarry2中的this指向发生错误期望输出的是obj,1,obj调用

  • 柯里化函数内部解决this指向
    请各位大佬指教
  • 在外部自行解决this指向的问题
    var name = "window";
    function fun(_this, a, b) {
      console.log(_this.name, a, b);
    }

    var obj = {
        name: "obj",
        fun,
    };

    var funCarry1 = curry(fun, window, 1);
    var funCarry2 = curry(obj.fun, obj, 1);

    funCarry1("全局调用"); // 输出 window, 1, wendow调用
    funCarry2("obj调用"); //  输出 obj, 1, obj调用

可以在进行柯里化时对将this固参(当然这要约定好)