最终效果:

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. P1852 [国家集训队]跳跳棋

    P1852 [国家集训队]跳跳棋 lca+二分 详细解析见题解 对于每组跳棋,我们可以用一个三元组(x,y,z)表示 我们发现,这个三元组的转移具有唯一性,收束性 也就是说,把每个三元组当成点,以转移 ...

  2. Python3 爬取微信好友基本信息,并进行数据清洗

    Python3 爬取微信好友基本信息,并进行数据清洗 1,登录获取好友基础信息: 好友的获取方法为get_friends,将会返回完整的好友列表. 其中每个好友为一个字典 列表的第一项为本人的账号信息 ...

  3. j2ee分布式缓存同步实现方案dlcache v1.0.1

    j2ee分布式缓存同步实现方案dlcache v1.0.1 发布 修复问题: 1.支持两个层次的缓存,典型的用于产品大类.产品小类,数据字典以及子项: 更新后见: pan http://pan.bai ...

  4. 微信小程序开发环境

    微信小程序开发环境 不忘初心,方得始终.初心易得,始终难守 小程序开发环境 开发工具下载地址:https://developers.weixin.qq.com/miniprogram/dev/devt ...

  5. 20145212罗天晨 注入shellcode实验及Retuen-to-libc实验

    注入shellcode实验 实验步骤 一.准备一段shellcode 二.设置环境 Bof攻击防御技术 1.从防止注入的角度来看:在编译时,编译器在每次函数调用前后都加入一定的代码,用来设置和检测堆栈 ...

  6. VC++实现获取文件占用空间大小的两种方法(非文件大小)

    // GetFileSpaceSize.cpp : Defines the entry point for the console application. // /***************** ...

  7. VC中GetLastError()获取错误信息的使用,以及错误代码的含义

    转载:http://www.seacha.com/article.php/knowledge/windows/mfc/2011/0423/335.html VC中GetLastError()获取错误信 ...

  8. JAVA I/O(一)基本字节和字符IO流

    最近再看I/O这一块,故作为总结记录于此.JDK1.4引入NIO后,原来的I/O方法都基于NIO进行了优化,提高了性能.I/O操作类都在java.io下,大概将近80个,大致可以分为4类: 基于字节操 ...

  9. myeclipse中文名字项目运行报错

    今天由于项目进行分支,负责开发迭代的功能对应不同的分支项目,没想到的是分支项目名称加上了功能的中文名字.要使用了resin发布项目的时候,报了 java.io.CharConversionExcept ...

  10. HBase底层存储原理——我靠,和cassandra本质上没有区别啊!都是kv 列存储,只是一个是p2p另一个是集中式而已!

    理解HBase(一个开源的Google的BigTable实际应用)最大的困难是HBase的数据结构概念究竟是什么?首先HBase不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库.另一个不 ...