JS中的 偏函数 和 柯里化
栏目: JavaScript · 发布时间: 5年前
内容简介:在计算机科学中,偏函数应用 是指将一些参数固定到一个函数,产生另一个较小的函数的过程。举个例子:基于这个函数,我们利用
什么是偏函数
在计算机科学中,偏函数应用 是指将一些参数固定到一个函数,产生另一个较小的函数的过程。
举个例子:
// 我们创建了一个做 乘法运算 的函数 function mult(a, b) { return a * b; };复制代码
基于这个函数,我们利用 bind
创造一个新的函数 double
:
let double = mult.bind(null, 2); console.log( double(3) ); // mult(2, 3) = 6; console.log( double(4) ); // mult(2, 4) = 8; console.log( double(5) ); // mult(2, 5) = 10; 复制代码
mult.bind(null, 2)
创造了一个新函数 double
,传递调用到 mult
函数,以 null
为 context
, 2
为第一个参数。其他参数等待传入。
这就是 偏函数应用 —— 我们创造了一个新函数,同时将部分参数替换成特定值。
什么时候使用偏函数
刚刚我们基于 mult
创建了一个新的函数 double
,这里我们再创建一个新的函数 triple
:
let triple = mult.bind(null, 3); console.log( triple(3) ); // mult(3, 3) = 9; console.log( triple(4) ); // mult(3, 4) = 12; console.log( triple(5) ); // mult(3, 5) = 15;复制代码
使用 偏函数
,我们能够从中受益的是:我们创建了一个独立的非匿名函数( double
, triple
)。我们可以使用它,而不需要每次都传入第一个参数,因为 bind
帮我们搞定了。
在其他的场景中,当我们有一个非常通用的函数,并且想要方便地获取它的特定变体,偏函数也是非常有用。
举个例子,我们拥有函数 post(signature, api, data)
。在调用请求方法的时候有着相同的用户签名,这里我们想要使用它的偏函数变体: post(api, data)
,表明该请求发送自同一用户签名。
什么是柯里化
有时候人们会把 偏函数应用 和另外一个名为 柯里化 的东西混淆,但那的确是另外一个和函数有关的有趣技术。
在 函数式编程语言 和 其他许多语言 中,柯里化(currying)提供了一种自动管理参数如何传递给函数和异常的方法。
简单来说, currying
是一项将一个调用形式为 f(a, b, c)
的函数转化为调用形式 f(a)(b)(c)
的技术。
举个例子:
function currying(fn) { return function(a) { return function(b) { return fn(a, b); }; }; } // 用法 function sum(a + b) { return a + b; } let carriedSum = currying(sum); console.log( carriedSum(1)(2) ); // 3复制代码
从上面的例子可以看到, carrying
的实现就是一系列的封装。
-
currying(fn)
的结果就是一层封装function(a)
。 -
当它被调用,就像
carriedSum(1)
这样,它的参数被保存到 词法环境 中,然后返回一层新的封装function(b)
。 -
然后
carriedSum(1)(2)
调用function(b)
,传入参数2
,它将调用传递给初始的多参数函数sum
。
结合之前的 偏函数
知识,我们可以看到, sum
函数在 柯里化
之后,逐个传递参数的时候返回的那一层封装:其实就是 sum
函数 的 偏函数变体
。
这可能也是大家容易将这个两个概念搞混的原因之一吧。
高级柯里化
高级的柯里化同时允许 函数正常调用 和 获取偏函数 。
我们可以实现一下 高级的柯里化:
function currying(fn) { return function curried(...args) { if(args.length>=fn.length) { // 传入的实参长度 >= 初始函数形参长度 的时候,则直接执行初始函数 return fn.apply(this, args); } else { // 否则 得到一个 偏函数,递归carried方法,直到获得所有参数后,直接执行 return function(...args2) { return curried.apply(this, args.concat(args2)); } } } } function sum(a, b, c) { return a + b + c; } let curriedSum = currying(sum); // 常规调用 console.log( curriedSum(1, 2, 3) ); // 6 // 得到 curriedSum(1)的偏函数,然后用另外两个参数调用它 console.log( curriedSum(1)(2, 3) ); // 6 // 完全柯里化调用 console.log( curriedSum(1)(2)(3) ); // 6复制代码
柯里化的目的是什么?
从上面的 高级柯里化 实现的例子中可以发现:
-
sum
函数 在 柯里化 之后对于使用并没有任何影响,仍然可以被正常调用。 - 在很多情况下,我们可以更方便的生成 偏函数 变体,可以更灵活的被我们使用。
总得来说, 柯里化的目的 就是在不影响 初始函数 的调用形式的情况下,更方便的让我们获得初始函数的 偏函数 变体。
最后,欢迎各位小伙伴留言,相互讨论。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Python 拓展之特殊函数(lambda 函数,map 函数,filter 函数,reduce 函数)
- Python 函数调用&定义函数&函数参数
- python基础教程:函数,函数,函数,重要的事说三遍
- C++函数中那些不可以被声明为虚函数的函数
- 017.Python函数匿名函数
- 纯函数:函数式编程入门
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Hadoop in Action
Chuck Lam / Manning Publications / 2010-12-22 / USD 44.99
HIGHLIGHT Hadoop in Action is an example-rich tutorial that shows developers how to implement data-intensive distributed computing using Hadoop and the Map- Reduce framework. DESCRIPTION Hadoop i......一起来看看 《Hadoop in Action》 这本书的介绍吧!