持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情
第一次看到柯里化这个词,感觉有点抽象,到底什么是柯里化呢?
首先,在编程中有如下之分:
- 函数式编程
- 命令式编程(比如 JQuery )
柯里化(Currying)是函数式编程的特点之一,由数学家柯里(Haskell Curry)提出。
柯里化
柯里化是指将一个函数从可调用的 f(a, b, c) 转换为可调用的 f(a)(b)(c)。简言之,是一种函数的转换。
柯里化的好处:简化代码结构,达到高内聚、低耦合。
形式
一般情况下,我们写一个函数来实现两数之和是这样的:
function sum(x, y){
return x + y
}
sum(1, 2) // 3
经过柯里化后,函数是这样的:
function sum(y){
return function (x){
return x + y
}
}
sum(1)(2) // 3
如果是更多的参数:
function sum(x) {
return function(y) {
return function(z) {
return x + y + z
}
}
}
sum(1)(2)(3)
也可以是箭头函数的形式:
const sum = x => y => z => {
return x + y + z
}
柯里化的优点
通过上面的例子可以看出,柯里化将多参数的函数转化为了单参数函数,并且柯里化在形式上和闭包很相似。
- 使每个函数的职责变得单一 (每次传入的参数在单一的函数中进行处理,处理完后在下一个函数中再使用处理后的结果)
- 延迟求值,需要的时候再进行求值
- 复用参数逻辑
如下面这段代码,想要计算某个固定值和另外一任意值之和,只需要传入1次固定值即可:
- 当执行 Currying() 函数并传入参数后,相当于 x = 2
- 再执行 sum() 函数并传入参数后,相当于 return 2 + 100
- 之后每次调用 sum(),只需传入一次参数
function Currying(x) {
return function(y) {
return x + y
}
}
const sum = Currying(2)
sum(100) // 102
sum(200) // 202
实现一个柯里化
lodash.js 以及 understore.js 各自也有实现柯里化的方法,除此之外我们也可以手动实现一个:
function createCurry(func, args) {
var len = func.length;// 函数参数的个数
var args = args || [];
return function () {
var _args = Array.prototype.slice.apply(arguments);
args.push(..._args);
console.log(args,'--')
if (args.length < len) {
return createCurry.call(this, func, args);
}
return func.apply(this, args);
}
}
function myFn(a, b, c) {
return a * b * c;
}
const multi = createCurry(myFn)
console.log(multi(2)(6)(10)); // 120
console.log(multi(2,6,10)); // 120
- 强制转化 arguments 为数组格式:
- [].slice.call(arguments)
- Array.prototype.slice.apply(arguments)