柯里化
背景
- 前不久面试某大厂被问到关于函数柯里化的问题,才疏学浅的我一脸懵逼,面试官以为自己没描述清楚,刻意把整个单词Currying拼了一遍,然后我该不知道的还是不知道。之前好像是在哪里见过,但是也没仔细去研究过,今天就来好好学习一番。
定义
- 先看下什么是柯里化,维基百科上的解释如下,其实就是把接受的多参数转为接受单一参数的一种技术。
在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术
优点
- 参数复用
- 提前返回 – 返回接受余下的参数且返回结果的新函数
- 延迟执行 – 返回新函数,等待执行
实例
- 普通函数
function add(x,y) {
return x + y;
}
add(1,2) //3
- 乞丐版柯里化写法
var add = function(x) {
return function(y) {
return x + y;
}
};
add(1)(2) //3
- 上面的实现参数是固定的,只能支持两个参数,如果想实现任意参数呢?如下:
- 通用版
function add() {
// 第一次执行时用来存储所有的参数
var args = [].slice.call(arguments);
// 利用闭包的特性保存args并收集所有的参数值
var adder = function () {
var _adder = function() {
[].push.apply(args, [].slice.call(arguments));
return _adder;
};
// 利用隐式转换的特性,当最后执行时进行隐式转换,并计算最终的值然后返回
_adder.toString = function () {
// 使用reduce来实现求和
return args.reduce(function (a, b) {
return a + b;
});
}
return _adder;
}
return adder.apply(null, [].slice.call(arguments));
}
// 输出结果,可自由组合的参数
console.log(add(1, 2, 3, 4, 5)); // 15
console.log(add(1, 2, 3, 4)(5)); // 15
console.log(add(1)(2)(3)(4)(5)); // 15
- 高阶版-ES6骚写法
const currying = (fn, ...args) =>
args.length < fn.length
//参数长度不足时,重新柯里化该函数,等待接受新参数
? (...arguments) => currying(fn, ...args, ...arguments)
//参数长度满足时,执行函数
: fn(...args);
function sumFn(a, b, c) {
return a + b + c;
}
var sum = currying(sumFn);
console.log(sum(2)(3)(5));//10
console.log(sum(2, 3, 5));//10
console.log(sum(2)(3, 5));//10
console.log(sum(2, 3)(5));//10
- 实现bind函数
function mybind(fn) {
return function() {
return fn.apply(this, arguments);
}
}
总结
- 柯里化的主要好处是参数复用,提前返回 ,延迟执行,还是需要熟练掌握,在面试中属于高频知识点。
参考
//www.greatytc.com/p/2975c25e4d71
https://juejin.im/entry/58b316d78d6d810058678579