译文开始

函数式编程是一种编程风格,这种编程风格就是试图将传递函数作为参数(即将作为回调函数)和返回一个函数,但没有函数副作用(函数副作用即会改变程序的状态)。

有很多语言采用这种编程风格,其中包括JavaScript、Haskell、Clojure、Erlang和Scala等一些很流行的编程语言。

函数式编程凭借其传递和返回函数的能力,带来了许多概念:

  • 纯函数
  • 柯里化
  • 高阶函数

    其中一个我们将要看到的概念就是柯里化。

    在这篇文章,我们将看到柯里化是如何工作以及它如何在我们作为软件开发者的工作中发挥作用。

什么是柯里化

柯里化是函数式编程中的一种过程,可以将接受具有多个参数的函数转化为一个的嵌套函数队列,然后返回一个新的函数以及期望下一个的内联参数。它不断返回一个新函数(期望当前参数,就像我们之前说的那样)直到所有参数都用完为止。这些参数会一直保持“存活”不会被销毁(利用闭包的特性)以及当柯里化链中最后的函数返回并执行时,所有参数都用于执行。

柯里化就是将具有多个arity的函数转化为具有较少的arity的函数。——kbrainwave

备注:术语arity(元数):指的是函数的参数个数,例如:

function fn(a, b) {
//...
}
function _fn(a, b, c) {
//...
}

函数fn有两个参数(即 2-arity函数)以及_fn有三个参数(即3-arity函数)。

因此,柯里化将一个具有多个参数的函数转化为一系列只需一个参数的函数。

下面,我们看一个简单的例子:

function multiply(a, b, c) {
return a * b * c;
}

这个函数接收三个数字并且相乘,然后返回计算结果。

multiply(1,2,3); // 6

接下来看看,我们如何用完整参数调用乘法函数。我们来创建一个柯里化版本的函数,然后看看如何在一系列调用中调用相同的函数(并且得到同样的结果)。

function multiply(a) {
return (b) => {
return (c) => {
return a * b * c
}
}
}
log(multiply(1)(2)(3)) // 6

我们已经将multiply(1,2,3)函数调用形式转化为multiply(1)(2)(3)多个函数调用的形式。

一个单独的函数已经转化为一系列的函数。为了得到三个数字1、2、3的乘法结果,这些数字一个接一个传递,每个数字会预先填充用作下一个函数内联调用。

我们可以分开这个multiply(1)(2)(3)函数调用步骤,更好理解一点。

const mul1 = multiply(1);
const mul2 = mul1(2);
const result = mul2(3);
log(result); // 6

我们来一个接一个地传递参数。首先传参数1到multiply函数:

let mul1 = multiply(1);

以上代码执行会返回一个函数:

return (b) => {
return (c) => {
return a * b * c
}
}

现在,变量mul1会保持以上的函数定义,这个函数接收参数b。

我们调用函数mul1,传入参数2:

let mul2 = mul1(2);

函数mul1执行后会返回第三个函数

return (c) => {
return a * b * c
}

这个返回的函数现在保存在变量mul2中。

本质上,变量mul2可以这么理解:

mul2 = (c) => {
return a * b * c
}

当传入参数3调用函数mul2时,

const result = mul2(3);

会使用之前传入的参数进行计算:a=1,b=2,然后结果为6。

log(result); // 6

作为一个嵌套函数,mul2函数可以访问外部函数的变量作用域,即multiply函数和mul1函数。

这就是为什么mul2函数能使用已经执行完函数中定义的变量中进行乘法计算。虽然函数早已返回而且已经在内存中执行垃圾回收。但是它的变量还是以某种方式保持“存活”。

备注:以上变量保持存活是闭包特性,不明白可以查看闭包相关文章了解更多

你可以看到三个数字每次只传递一个参数应用于函数,并且每次都返回一个新的函数,值得所有的参数用完为止。

下面来看一个其他的例子:

function volume(l,w,h) {
return l * w * h;
}
const aCylinder = volume(100,20,90) // 180000

上面是一个计算任何实心形状体积的函数。

这个柯里化版本将接受一个参数以及返回一个函数,该函数同样也接受一个参数和返回一个新的函数。然后一直这样循环/继续,直到到达最后一个参数并返回最后一个函数。然后执行之前的参数和最后一个参数的乘法运算。

function volume(l) {
return (w) => {
return (h) => {
return l * w * h
}
}
}
const aCylinder = volume(100)(20)(90) // 180000

就像之前的multiply函数那样,最后的函数只接受一个参数h,但是仍然会对那些早已执行完返回的函数作用域中里的其他变量执行操作。能这样操作是因为有闭包的特性。

译者注:以上写的很啰嗦,感觉另外的例子完全就是重复说明。

柯里化背后的想法其实是获取一个函数并派生出一个返回特殊函数的函数。

柯里化在数学方面的应用

我有点喜欢数学说明

【译】理解JavaScript中的柯里化的更多相关文章

  1. 浅谈JavaScript中的柯里化函数

    首先,不可避免的要引经据典啦,什么是柯里化函数呢(from baidu): 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返 ...

  2. JavaScript中的柯里化

    转载自:https://www.cnblogs.com/zztt/p/4142891.html 何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Ha ...

  3. javascript中利用柯里化函数实现bind方法

    柯理化函数思想:一个js预先处理的思想:利用函数执行可以形成一个不销毁的作用域的原理,把需要预先处理的内容都储存在这个不销毁的作用域中,并且返回一个小函数,以后我们执行的都是小函数,在小函数中把之前预 ...

  4. JS中的柯里化(currying)

    何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字命名). 柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参 ...

  5. JS中的柯里化(currying) 转载自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]

    JS中的柯里化(currying) by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wordpr ...

  6. JS中的柯里化及精巧的自动柯里化实现

    一.什么是柯里化? 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术.这个技术由 C ...

  7. JavaScript函数式编程——柯里化

    柯里化原理 如何实现柯里化 柯里化的应用 一.柯里化原理 柯里化:在数学和计算机科学中,柯里化是一种使用多个参数的一个函数转换成一系列使用一个参数的函数的技术. 前端使用柯里化的用途主要就应该是简化代 ...

  8. javascript之反柯里化(uncurrying)

    在JavaScript中,当我们调用对象的某个方法时,其实不用去关心该对象原本是否被设计为拥有这个方法,这是动态类型语言的特点.可以通过反柯里化(uncurrying)函数实现,让一个对象去借用一个原 ...

  9. 简单粗暴详细讲解javascript实现函数柯里化与反柯里化

    函数柯里化(黑人问号脸)???Currying(黑人问号脸)???妥妥的中式翻译既视感:下面来一起看看究竟什么是函数柯里化: 维基百科的解释是:把接收多个参数的函数变换成接收一个单一参数(最初函数的第 ...

随机推荐

  1. P3203 [HNOI2010]弹飞绵羊 —— 懒标记?分块?LCT?...FAQ orz

    好久没写博客了哈,今天来水一篇._(:з」∠)_ 题目 :弹飞绵羊(一道省选题) 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏 ...

  2. 微信小程序-下拉松开弹不回去顶部留一段空白

    解决办法: 空白的出现有可能是多次触发下拉事件导致请求过多导致页面反应延迟. 在 onPullDownRefresh 事件里加setTimeout事件延迟下下拉刷新的事件. /** * 页面相关事件处 ...

  3. 关于iwinfo的调试

    在调试 主动扫描时,调用命令 “iwinfo  wlan0 scan”时, 在iwinfo中添加的调试语句没有打印和记录到log中去. 后查看iwinfo的makefile发现,在生成iwinfo程序 ...

  4. centos6.5环境wget报错Unable to establish SSL connection

    centos6.5环境wget报错Unable to establish SSL connection [root@centossz008 src]# wget --no-check-certific ...

  5. mysql select in 怎么优化

    2017年7月10日 22:36:54 星期一 原理: 把select where in 变换成 "where = " 或者 "where between and &qu ...

  6. 如何安装和配置RabbitMQ

    今天开始一个小小的练习,学习一下安装和配置RabbitMQ,为什么要学它,因为WCF可以完全兼容和使用RabbitMQ了.我们新的大数据系统需要使用消息队列,所以就开始研究一下,把它重新封装一下,更便 ...

  7. MYSQL修改字段

    当字段为空则插入0,不为空则原来的值  UPDATE t_pm_scheduleSET lesson_room_id1 = IFNULL(lesson_room_id1, 0), lesson_roo ...

  8. cemtos7.2搭建samba

    1背景 转到Linux有段时间了,vim操作还不能应对工程代码,之前一直都是Gnome桌面 + Clion 作开发环境,无奈在服务器上没有这样的环境, 看同事是(Windows)Source Insi ...

  9. AES对数据进行加密与解密

    AES对数据进行加密与解密随着对称密码的发展,DES数据加密标准算法由于密钥长度较小(56位),已经不适应当今分布式开放网络对数据加密安全性的要求,因此1997年NIST公开征集新的数据加密标准,即A ...

  10. SqlBulkCopy 之 Received an invalid column length from the bcp client for colid 5.

    SqlBulkCopy 批量复制报错: Received an invalid column length from the bcp client for colid 5. 翻译:从bcp客户端收到一 ...