最终效果:

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. P2503 [HAOI2006]均分数据

    P2503 [HAOI2006]均分数据 模拟退火+dp (不得不说,我今天欧气爆棚) 随机出1个数列,然后跑一遍dp统计 #include<iostream> #include<c ...

  2. 02: tornado进阶篇

    目录:Tornado其他篇 01: tornado基础篇 02: tornado进阶篇 03: 自定义异步非阻塞tornado框架 04: 打开tornado源码剖析处理过程 目录: 1.1 自定制t ...

  3. Android Studio导入包

    1.复制jar包,打开工程,以project形式打开,在libs下面粘贴: 2.右键jar包,add as library.

  4. CF 316E3 Summer Homework(斐波那契矩阵+线段树)

    题目链接:http://codeforces.com/problemset/problem/316/E3 题意:一个数列A三种操作:(1)1 x y将x位置的数字修改为y:(2)2 x y求[x,y] ...

  5. 搭建最新版本的Android开发环境

    只为成功找方法,不为失败找借口! Android开发学习总结(一)——搭建最新版本的Android开发环境 最近由于工作中要负责开发一款Android的App,之前都是做JavaWeb的开发,Andr ...

  6. jQuery:ajax处理html页面

    源码: $.ajax({ url: url, success: function (data) { var reg = /<body>[\s\S]*<\/body>/g; ]; ...

  7. AlexNet网络结构特点总结

    参考论文:ImageNet Classification with Deep Convolutional Neural Networks 1.特点 1.1 ReLU Nonlinearity的提出 Re ...

  8. gulp常用命令

    gulp 默认的执行的命名文件为gulpfile 换成其他命名就识别不了 因为需要安装两次gulp或者说其他插件,一个是全局-g安装一个是本地目录安装, 本地目录安装时目录移动或者名字被改变就会失效提 ...

  9. js中可以直接使用id而不用获取id

    先来看一个例子: 不获取 id 也可以使用 id 元素. <!-- Author: XiaoWen Create a file: 2017-01-11 13:58:01 Last modifie ...

  10. C#完美读取CSV

    /// <summary>         /// 将DataTable中数据写入到CSV文件中         /// </summary>         /// < ...