JavaScript中的函数柯里化
柯里化的定义与理解:
柯里化也是属于函数式编程里面一个非常重要的概念。
维基百科定义:
在计算机科学中,柯里化,又以为卡瑞化或加里化;
是把接收多个参数的函数,变成一个接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数,而且返回结果的新函数的技术;
柯里化生声称“如果你固定某些参数,你讲得到接受余下参数的一个函数”。
个人理解小总结:
只传递给函数一个部分参数来调用它,让它返回一个函数去处理剩余的参数,这个过程称为柯里化。
如下示例代码展示了什么是函数柯里化:
// 正常情况下 代码 function sum1 (num1, num2, num3) { return num1 + num2 + num3 } var result1 = sum2(1, 2, 3) console.log(result1) // 6 // 函数柯里化 function sum2 (num1) { return function sum3 (num2) { return function sum4 (num3) { return num1 + num2 + num3 } } } var result2 = sum2(1)(2)(3) console.log(result2) // 6 // 简化柯里化代码 (其实就是使用箭头函数简写) var sum3 = x => y => z => { return x + y + z } var result3 = sum3(1)(2)(3) console.log(result3) // 6
看完上述示例代码后有什么想法呢?
我明明可以一步写完就像第一段代码那样,我干嘛还要柯里化,写成第二段那样麻烦。
接下来就为大家解疑:
在函数式编程中,我们其实往往希望一个函数处理的问题尽可能的单一,而不是将一大堆的处理过程交给一个函数来处理;
那么我们是否就可以将每次传入的参数在单一的函数中进行处理,处理完后在下一个函数中再使用处理后的结果。让函数的职责单一。
并且经过柯里化的函数有的地方可以直接进行逻辑复用。
使用柯里化的好处一:单一职责的原则
还是利用上面的代码进行描述
现在我们修改约束条件为:将第一个参数加上2,第二个参数乘以2,第三个参数平方
如下示例代码展示了,函数柯里化的单一职责原则:
// 方式一:正常情况下我们会将简单的处理逻辑这样写(代码逻辑很少) // 但是如果num1的处理逻辑有20行 ,num2的处理逻辑有20行 ,num3的处理逻辑有20行 ,这样处理起来函数会变得很复杂,之后要修改也不容易去操作 function sum1 (num1, num2, num3) { num1 = num1 + 2 num2 = num2 * 2 num3 = num3 * num3 return num1 + num2 + num3 } var result1 = sum1(1, 2, 3) console.log(result1) // 16 // 方式二: // 函数柯里化单一职责原则,每一个函数中都有一个对应的职责,修改起来也很方便 function sum2 (num1) { num1 = num1 + 2 return function (num2) { num2 = num2 * 2 return function (num3) { num3 = num3 * num3 return num1 + num2 + num3 } } } var result2 = sum2(1)(2)(3) console.log(result2) // 16
两种方式的输出结果一致,但第二种使用了柯里化实现了单一职责原则
使用柯里化的好处二:逻辑的复用
案例一: 假设在程序中,需要经常把5和一个数值相加的出结果,实现方法示例代码如下:
// 方式一: function sum (x, y) { return x + y } console.log(sum(5, 1)) console.log(sum(5, 2)) // 方式二:函数柯里化 function add (num1) { return function (num2) { return num1 + num2 } } // 使用方法一: var result1 = add(5)(10) console.log(result1) // 15 // 使用方法二:直接将add(5)存储在一个变量中,使用的时候只需要传入要与5相加的数字 var add5 = add(5) var result2 = add5(10) console.log(result2) // 15
案例二: 假设在程序中,需要打印日志获取时间,类型,文本描述,示例代码如下:
// 方式一: function log1 (date, type, message) { console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]: [${message}]`) } log1(new Date(), 'debug', '参数错误') // [22:49][debug]: [参数错误] log1(new Date(), 'future', '新增功能') // [22:49][future]: [新增功能] // 方式二: 函数柯里化 var log2 = date => type => message => { console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]: [${message}]`) } log2(new Date())('debug')('参数错误') // [22:49][debug]: [参数错误] log2(new Date())('future')('新增功能') // [22:49][future]: [新增功能] // (1)函数柯里化 - 逻辑复用,假设当前日志打印都是获取的当前时间,柯里化代码优化为: var logDate = log2(new Date()) logDate('debug')('参数错误') // [22:49][debug]: [参数错误] logDate('future')('新增功能') // [22:49][future]: [新增功能] // (2)函数柯里化 - 逻辑复用,假设当前日志打印都是获取的当前时间与类型都为debug,柯里化代码优化为: var logDateAndType = log2(new Date())('debug') logDateAndType('参数错误') // [22:49][debug]: [参数错误] logDateAndType('路由错误') // [22:49][debug]: [路由错误]
看完全文是不是对柯里化有了深入的了解,如果感觉文章写得不错,就点个赞吧。下一篇文章更新柯里化的实现原理哦,拥有自动实现函数柯里化的方法。