最终效果:

var greet = function(greeting, name) {
return greeting + ' ' + name;
}; var sayHelloTo = _.partial(greet, 'hello');
sayHelloTo('fred');
// => 'hello fred'

来自:http://lodashjs.com/docs/#_partialfunc-partials

除非你已经使用过其他的函数式编程,不然你可能对下面这两个概念很陌生:“偏函数应用”和“函数柯里化“。

偏函数应用,英文是partial application,也可以译作“局部应用”、“部分应用”、“偏应用”
函数柯里化,英文是currying,也可以译作“局部套用”、“加里化”、“卡瑞化”

话虽如此,但是假如你一旦理解了这两个概念,你就完全可以在自己的代码里使用他们。

Functions

即使你已经很熟悉JavaScript的function, 知道function可以作为返回值,可以作为参数。
但是我还是推荐你读一下这个第一部分。如果不需要,也可以跳过,直接看局部应用的章节。

我们首先看一个非常基础的例子:

function add(a, b) {
return a + b;
} add(1, 2); // 3
add(1, 3); // 4
add(1, 10); // 11
add(1, 9000); // 9001

尽管上面的例子是非常的简单,但是还是演示出了我们反复调用一个function的场景,并且每次传入的第一个参数都是相同的,在上面的代码里就是数字1

Functions返回Functions

我们也可以创建一个叫做makeAdder的function,这个function会返回另一个可以传入参数的function。(像这种可以用来创建其他function或object的function,一般会叫做工厂 - factories)

返回的函数,如果往里面传入参数调用,可以把传入的参数值和原来设的参数值,返回相加的结果。

// More general function.
function add(a, b) {
return a + b;
} add(1, 2); // 3
add(10, 3); // 13 // More specific function generator.
function makeAdder(a) {
return function(b) {
return a + b;
};
} // More specific functions.
var addOne = makeAdder(1);
addOne(2); // 3
addOne(3); // 4 var addTen = makeAdder(10);
addTen(2); // 12
addTen(3); // 13

上面的代码之所以可行,是因为JavaScript支持闭包的功能,由于闭包的存在,使得function可以访问到这个function外部的变量,甚至在调用这个function时的作用域的外层。

除此之外,在JavaScript里面,function是一等公民。正因为如此,function可以接受function作为参数,也可以返回function.

闭包和函数这个一等公名经常一起配合着工作:使得返回的function可以继续使用传入的参数。

上面的代码给我们提供了一些方便,我们可以不再使用add(1, 2),而直接使用addOne(2),但是实现这个并不是不需要付出代价的。

首先,实际做加法的逻辑在上面两个例子的代码中还是重复的,这样还是会有些问题。

其次,对每个类似于上面的加法场景,用这种方式去独立除不同的逻辑,我们将需要手工创建makeSomething的工厂function。

Functions接受Functions

下面的逻辑步骤是创建一个更普遍的工厂function,不仅接受一个要绑定的参数,也会接受一个function,这个function里面包含了所有的核心逻辑。(传入到其他function的function,一般被成为回调函数-callbacks)

用这种方式,一个单独的工厂function能够被用来创建function绑定。

注意,原始的function被没有被更新,并且他们的行为也不会改变。他们很容易被调用。

// Relatively flexible, more specific function generator.
function bindFirstArg(fn, a) {
return function(b) {
return fn(a, b);
};
} // More general functions.
function add(a, b) {
return a + b;
} add(1, 2); // 3 function multiply(a, b) {
return a * b;
} multiply(10, 2); // 20 // More specific functions.
var addOne = bindFirstArg(add, 1);
addOne(2); // 3
addOne(3); // 4
addOne(10); // 11
addOne(9000); // 9001 var multiplyByTen = bindFirstArg(multiply, 10);
multiplyByTen(2); // 20
multiplyByTen(3); // 30
multiplyByTen(10); // 100
multiplyByTen(9000); // 90000

上面这段代码,亮点不在于它可以将某个参数绑定到任意的function,并且这个参数作为绑定的function的第一个参数,它还能将方法绑定它自己身上作为第一个参数,因此创建了一个可绑定的function

想想这种情况:假如bindFirstArg能够将第一个参数绑定到一个function,但是这个function可以接受两个参数,比如传进去1和10,1用来加,10用来乘。
bindFirstArg可以接受两个2参数,假如第一个参数是它自己,也就是bindFirstArg可以用来绑定它自己。

看下面的例子:

// More specific function generator.
var makeAdder = bindFirstArg(bindFirstArg, add); // More specific functions.
var addOne = makeAdder(1);
addOne(2); // 3
addOne(3); // 4 var addTen = makeAdder(10);
addTen(2); // 12
addTen(3); // 13

javascript里的偏函数——本质函数式编程+闭包,返回函数的更多相关文章

  1. python函数式编程之返回函数、匿名函数、装饰器、偏函数学习

    python函数式编程之返回函数 高阶函数处理可以接受函数作为参数外,还可以把函数作为结果值返回. 函数作为返回值 def laxy_sum(*args): def sum(): ax = 0; fo ...

  2. Learning Python 012 函数式编程 2 返回函数 匿名函数 装饰器 偏函数

    Python 函数式编程 2 返回函数 返回函数的意思就是:函数作为返回值.(高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回.) 举个例子:实现一个可变参数的求和. 正常的函数: de ...

  3. Python学习札记(二十四) 函数式编程5 返回函数

    参考:返回函数 NOTE 1.高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. eg.求和函数 #!/usr/bin/env python3 def calsums(*args): a ...

  4. JavaScript函数式编程(纯函数、柯里化以及组合函数)

    JavaScript函数式编程(纯函数.柯里化以及组合函数) 前言 函数式编程(Functional Programming),又称为泛函编程,是一种编程范式.早在很久以前就提出了函数式编程这个概念了 ...

  5. 【Python】[函数式编程]高阶函数,返回函数,装饰器,偏函数

    函数式编程高阶函数 就是把函数作为参数的函数,这种抽象的编程方式就是函数式编程.--- - -跳过,不是很理解,汗 - ---

  6. 从函数式编程到Ramda函数库(二)

    Ramda 基本的数据结构都是原生 JavaScript 对象,我们常用的集合是 JavaScript 的数组.Ramda 还保留了许多其他原生 JavaScript 特性,例如,函数是具有属性的对象 ...

  7. 从函数式编程到Ramda函数库(一)

    函数式编程是种编程方式,它将电脑运算视为函数的计算.函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值).和指令式编程相比, ...

  8. Python之路Python作用域、匿名函数、函数式编程、map函数、filter函数、reduce函数

    Python之路Python作用域.匿名函数.函数式编程.map函数.filter函数.reduce函数 一.作用域 return 可以返回任意值例子 def test1(): print(" ...

  9. 跟着ALEX 学python day3集合 文件操作 函数和函数式编程 内置函数

    声明 : 文档内容学习于 http://www.cnblogs.com/xiaozhiqi/  一. 集合 集合是一个无序的,不重复的数据组合,主要作用如下 1.去重 把一个列表变成集合 ,就自动去重 ...

随机推荐

  1. Java项目导出为jar包+导出第三方jar包+使用命令行调用+传参

    Java项目导出为jar包+导出第三方jar包+使用命令行调用+传参 一.打包 情况1:不需要向程序传参数,并且程序没有使用第三方jar包 Eclipse上导出jar: 然后选择一个java文件作为入 ...

  2. 简单的Django向HTML展示动态图片 案例——小白

    目标:通过Django向HTML传送图片展示 我的天哪,真是膈应人,网上的案例都不适合我,感觉所有的解决办法在我这里都不行. 好吧~ 是我菜,看不懂人家的代码,那句话叫啥来着?一本好经被傻和尚念歪了. ...

  3. Email移动的原理

    1.从数据库中得到被移动邮件的uid: 2.选择移动邮件所属folder,即SelectFolder; 3.调用copymessage(path,vmime::net::messageset::byU ...

  4. 如何替换vi的配色方案

    答: 1.获取配色方案 git clone git://github.com/altercation/vim-colors-solarized.git ~/.vim/bundle/vim-colors ...

  5. hdu 3698 UVA1490 Let the light guide us 线段树优化DP

    题目链接 and 题目大意 hdu3698 但是 hdu的数据比较弱,所以在这luogu提交吧UVA1490 Let the light guide us 有一个\(n*m\)的平原,要求每行选一个点 ...

  6. POJ 2752 Seek the Name, Seek the Fame(KMP中next的理解)题解

    题意: 要求你给出每个前后缀相同的串的长度,比如: "alala"的前缀分别为{"a", "al", "ala", &q ...

  7. Trailing Zeroes (III) (二分)题解

    You task is to find minimal natural number N, so that N! contains exactly Q zeroes on the trail in d ...

  8. spring集成mybatis后,打印SQL语句

    网上说mybatis的早前版本配置打印sql还比较简单,在3.0.6之后配置方式修改了. 现在的spring-mybatis.xml配置如下: <bean id="sqlSession ...

  9. 自定义redis序列化工具

    redis一个优点就是可以将数据写入到磁盘中. 我们知道写入磁盘的数据实际上都是以字节(0101这样的二进制数据)的形式写入的. 这意味着如果我们要将一个对象写入磁盘,就必须将这个对象序列化. jav ...

  10. 51nod 1050 循环数组最大子段和 单调队列优化DP

    题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1050 这个呢,这个题之前 求一遍最大值  然后求一遍最小值 ...