稍微激进的标题可能会致使标题党误读了这篇博客。我要澄清一下:我本人喜欢函数式编程。个人主要观点是:
JavaScript最好的特性之一就是能够适用多种不一样的编程风格。所以:若是你Currying编程到没有任何提到的替代品适合你,那么你就肆意适用Curring吧。 若是你这样作,请保持你的代码风格一致。而且准备好你的代码与生态系统的其余部分稍有不一样。javascript
Currying在函数式编程中是一种流行的技术, 它有助于偏函数应用。html
其思想以下:若是您不为函数提供全部参数,则返回一个函数。函数的入参是剩余参数,其输出是原始函数的结果。java
例如,若是想要数组的全部元素加2,并有一个二进制函数Add(x,y),则能够以下所示:git
const arr = [1, 2, 3]; arr.map(add(2)); // [3, 4, 5]`
顺便说一下,具备自动currying的函数式编程语言一般具备能够这样使用的加法操做符。es6
你有两个选择执行add()方法来支持currying。github
ES6箭头函数能够很容易地手动编写柯里函数:编程
const add = x => y => x + y; // 等价于(译者注) function add(x) { return function(y) { return x + y; } }
以下所示你能够这样执行add()数组
add(2)(3); // 5
一个函数持有多个须要转化的嵌套函数,多数具备自动currying的函数式编程语言在语法上add(1, 2) 和add(1)(2)没有什么区别。app
2.2 重载 currying编程语言
一些库提供了重载的函数。 根据参数数量,这些重载函数中的每个都会有不一样的表现:
这种形式的curring的实现以下。
function add(...args) { if (args.length < 2) { return add.bind(this, ...args); } const [x, y] = args; return x + y; }
能够编写一个工具函数,将普通函数转换为这种实现。
柯里化是一种有助于偏函数应用的函数转化技术。
若是想要在JavaScript使用currying编程你有两选择:
使用真currying
使用重载currying
若是你转换了内置函数或方法来适应你的currying风格,那么你将面对不少问题。
注意:并不是全部这些缺点一样重要。
javascript中具名参数能够经过Object字面量模拟(Simulating named parameters ES6中)我喜欢这种绑定参数的方式,他使得代码更有自我描述性。不是全部currying的javascript库都支持具名参数。
一般状况下在函数的后面使用()就能够执行该函数。Currying后你必须清楚的知道函数函数foo中函数的个数。以便知道 foo(123)执行后获得的是一个函数仍是函数的结果。
比较下面两个偏函数应用
foo(123, ?) _ => foo(123, _)
foo()支持多种方式调用。
使用具名参数,在curry中会丢失更多信息
arr.map(findCity({ latitude: 48.137154 })); // curried arr.map(_ => findCity({ latitude: 48.137154, longitude: _ }))
静态类型系统(TypeScript,Flow,...)会减小错误,可是替代方法仍然更易于阅读。
若是忽略参数,就会使用函数的默认参数
function add(x=0, y=0) { return x + y; }
默认参数可使的添加参数更加透明而且不会破坏现有调用,这种技术对命名参数特别有用,我常常用来保证通用函数和方法的适用性。
使用参数默认值省略参数意味着使用默认值,使用currying省略参数意味着返回偏函数, 所以二者有冲突。
使用Currying,参数对函数开始是对配置和结束运算都很重要。而Javascript中并非这样。
例如parseInt()的签名是:
parseInt(s : string, radix : number);
这使得它不可能这样预先填充基数:
['32', '17', '5'].map(parseInt(10)) // doesn’t work
当谈到Currying,人们一般想要的是偏函数编程。让咱们看看下面的例子重载Currying并探索替代方案。
[1, 2, 3].map(add(2))
替代 1: .bind().
[1, 2, 3].map(add.bind(null, 2))
替代 2: arrow functions.
[1, 2, 3].map(x => add(2, x))
替代 3: an upcoming proposal for partial application.
[1, 2, 3].map(add(2, ?))
注:语法固定,提案处于早期阶段。
这个建议的好处在于,它能够很好地处理任意的签名,而且具备很好的描述性语法。