函数柯里化

89 阅读2分钟

函数柯里化

什么是柯里化

简单来说,一般函数中如果需要传参,则必须所有参数都传入之后才能开始执行该函数。而在函数柯里化之后,可以将参数分开传入,函数依然可执行。可以理解为延迟接受参数。

例子

// 一般函数
function fn1 (a, b) {
    return a + b ;
}

fn1(1, 2);  // 输出结果为 3

// 柯里化函数
function fn2 (a) {
    return function (b) {
        return a + b;
    };
};

fn2(1)(2) // 输出结果为 3

原理

在JS中的函数柯里化是利用的是闭包的原理,通过闭包返回一个函数,该函数中的参数以及变量将被缓存,便于遍历调用。

实现

简易版

// 箭头函数版
const people = name => age => sex => console.log('名字:'name, '年龄:'age, '性别:'sex);

// 普通函数版
function people(name) {
  return function age(age) {
    return function sex(sex) {
      console.log('名字:' + name, '年龄:' + age, '性别:' + sex);
    };
  };
}

people('张三')(18)('男') // 输出结果为 "名字:张三 年龄:18 性别:男"

在这种情况下只能单个参数去传

改进版

const people = (name, age, sex) => console.log('名字:' + name, '年龄:' + age, '性别:' + sex);
const toCurry = (fn, ags)  => 
	fn.length <= ags.length ? // fn.length 为参数的长度
      fn(...arguments) : toCurry(fn, ags, ...arguments )

const newFn = toCurry(people);

newFn('张三',18,'男');
newFn('张三')('18,''');
newFn('张三')(18)('男');
newFn()()()()()('张三')(18)('男');
// 以上输出结果皆为 "名字:张三 年龄:18 性别:男"

实际用途

函数在柯里化之后,可先调用函数,传入固定的参数,减少之后的每次调用需要重复调参

// 柯里化函数写法
function add(x) {
  return function(y) {
    return x + y;
  };
}

// 调用柯里化函数
const add5 = add(5);
console.log(add5(3)); // 8
console.log(add5(7)); // 12

实际例子

// 请求接口,接口地址一样,但是配置config信息参数不一样,每次都需要重复传入接口地址参数'www.abc.com'
request1 ('www.abc.com',{'id': '1','color': 'red'});
request1 ('www.abc.com',{'id': '2','color': 'blue'});

// 柯里化之后,只需要传入第二个参数即可
const request2 = toCurryRequest(request('www.abc.com'));
console.log(request2({'id': '1','color': 'red'})); 
console.log(request2({'id': '2','color': 'blue'})); 

优劣

好处

  • 参数复用
  • 增加函数的灵活性

坏处

  • 性能消耗增加,存在闭包,使用额外内存存储数据
  • 可能会增加代码复杂性