JavaScript函数编程-Ramdajs

在JavaScript语言世界,函数是第一等公民。JavaScript函数是继承自Function的对象,函数能作另一个函数的参数或者返回值使用,这便形成了我们常说的高阶函数(或称函数对象)。这就构成函数编程的第一要素。在JavaScript世界中有很多的函数式编程库能辅助我们的JavaScript函数式体验,在它们之中最为成功的要数Underscore或lodash。

如下lodash实例代码:

var users = [
  { 'user': 'barney',  'age': 36 },
  { 'user': 'fred',    'age': 40 },
  { 'user': 'pebbles', 'age': 18 }
];

var names = _.chain(users)
    .pluck('user')
    .join(" , ")
    .value();
console.log(names);

它以链式、惰性求值著称,形成了一套自有的DSL风格。更多关于lodash的编程可以参见博主的另一篇文章JavaScript工具库之Lodash

函数式思想展现的是一种纯粹的数学思维。函数并不代表任何物质(对象,相对于面向对象思想而言),而它仅仅代表一种针对数据的转换行为。一个函数可以是原子的算法子(函数),也可以是多个原子算法子组成的组合算法子。它们是对行为的最高抽象,具有非凡的抽象能力和表现力。

虽然Underscore或lodash也提供了.compose(或.flowRight)函数来实现函数组合的能力,但ramdajs具有更强的组合力。

ramdajs是一个更具有函数式代表的JavaScript库,可以在这里了解更多关于它的信息http://ramdajs.com/0.17/。它的这种能力主要来自它自有的两大能力:自动柯里化和函数参数优先于数据。

自动柯里化

在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的,尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的。

在理论计算机科学中,柯里化提供了在简单的理论模型中比如只接受一个单一参数的lambda 演算中研究带有多个参数的函数的方式。

ramdajs利用这一技术,默认所有API函数都支持自动柯里化。这为它提供了可以将另一个函数组合的先决条件。如常用的map操作需要接受两个参数,在ramdajs中可以如下两种方式实现:

R.map(function(item){
    return item *2;
 },
 [2,3,5]
); //输出[4, 6, 10]

var map = R.map(function(item){
    return item *2;
});
map([2,3,5]); //输出[4, 6, 10]

如果我们传入2个完备的参数,则R.map函数将会直接执行。否则,它将返回另一个函数,等待参数完备时才执行。

关于JavaScript函数的柯里化,你还可以从博主的《JavaScript函数柯里化》中了解更多http://www.cnblogs.com/whitewolf/p/4495517.html

函数参数优先于数据

在UnderScore和lodash这类库中,都要求首先传入数据,然后才是转换函数。而在ramdajs却是颠覆性的改变。在它的规约中数据参数是最后一个参数,而转换函数和配置参数则优于数据参数,排在前面。

将转换函数放置在前面,再加上函数的自动柯里化,就可以在不触及数据的情况下,将一个函数算法子包装进另一个算法子中,实现两个独立转换功能的组合。

假设,我们拥有如下两个基础算法子:

  1. R.multiply(a, b):实现 a *b; 2:R.map(func, data):实现集合 a –> b的map。

因为可以自动柯里化,所以有

R.multiply(10, 2); // 20

R.multiply(10) (2); // 20

所以上面对数组map的例子则可以转为如下形式:

R.map(R.multiply(2)) ([2, 5, 10, 80]); // [4, 10, 20, 160]

R.map(R.multiply(2))的返回值也是一个函数,它是一个组合转换函数。它组合了map和multiply行为。它利用R.map组合封装了R.multiply(2)返回的柯里化函数,它等待map函数传入对应的被乘数。

ramdajs的组合

有了上面的两个条件,再加上ramdajs为我们提供的R.compose方法,我们就能很容易的实现更多算法子的组合。R.compose是从右向左执行的数据流向。

用ramdajs的组合来实现开篇lodash一样的用户名拼接的例子,则我们可以分为2个算法子的组合:

  1. R.pluck(prop):选择对象固定属性;
  2. R.join(data):对数组的字符串拼接。

则代码如下所示:

var joinUserName = R.compose(R.join(" , "), R.pluck("user"));
joinUserName(users); // "barney , fred , pebbles"

这里的函数式组合可表示为下图:

如果我们希望join用户的年龄,则如下:

var joinUserAge = R.compose(R.join(" , "), R.pluck("age"));
joinUserAge(users); // "36 , 40 , 18"

假设我们希望输出的不是用户年龄,而是用户生日,则我们可以轻易组合上一个减法的算法子:

  1. R.subtract(a, b):实现 a – b 数学算法。

则代码如下:

var joinUserBrithDay = R.compose(R.join(","),R.map(R.subtract(new Date().getFullYear())),R.pluck("age"));
joinUserBrithDay(users); // "1979,1975,1997"

再如,我们希望获取最年轻的用户:

lodash实现:

_.chain(users)
  .sortBy("age")
  .first()
  .value();

ramdajs则,可以组合获取第一个元素的R.head算法子和排序算法子R.sortBy:

var youngestUser = R.compose(R.head, R.sortBy(R.prop("age")));
youngestUser(users); // Object {user: "pebbles", age: 18}

比如我们希望获取年长的用户,则只需再组合一个反序排列的算法子R.reverse:

var olderUser = R.compose(R.head, R.reverse, R.sortBy(R.prop("age")));
olderUser(users); // Object {user: "fred", age: 40}

希望你也能像我一样喜欢上ramdajs,关于它的更多资料,请参见其官网 http://ramdajs.com/0.17/

作者:破  狼 
出处:http://www.cnblogs.com/whitewolf/ 
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。该文章也同时发布在我的独立博客中-个人独立博客博客园--破狼51CTO--破狼。http://www.cnblogs.com/whitewolf/p/javascript-functional-programming-Ramdajs.html

时间: 2024-10-31 06:55:37

JavaScript函数编程-Ramdajs的相关文章

函数式JavaScript编程指南_javascript技巧

简介 你是否知道JavaScript其实也是一个函数式编程语言呢?本指南将教你如何利用JavaScript的函数式特性.  要求:你应当已经对JavaScript和DOM有了一个基本的了解. 写这篇指南的目的是因为关于JavaScript编程的资料太多了但是极少的资料提到了JavaScript的函数式特性.在本指南中,我只会讲解这些基本知识而不会深入其它的函数式语言或这是Lambda算子.  你可以点击所有的例子然后你所看到的代码就会被执行,这样就可以令指南变得具有交互性.你也可以使用这个沙箱来

Javascript函数式编程语言_javascript技巧

函数式编程语言 函数式编程语言是那些方便于使用函数式编程范式的语言.简单来说,如果具备函数式编程所需的特征, 它就可以被称为函数式语言.在多数情况下,编程的风格实际上决定了一个程序是否是函数式的. 是什么让一个语言具有函数式特征? 函数式编程无法用C语言来实现.函数式编程也无法用Java来实现(不包括那些通过大量变通手段实现的近似函数式编程). 这些语言不包含支持函数式编程的结构.他们是纯面向对象的.严格非函数式的语言. 同时,纯函数语言也无法使用面向对象编程,比如Scheme.Haskell以

javascript函数式编程实例分析_javascript技巧

本文实例讲述了javascript函数式编程.分享给大家供大家参考.具体分析如下: js像其他动态语言一样是可以写高阶函数的,所谓高阶函数是可以操作函数的函数.因为在js中函数是一个彻彻底底的对象,属于第一类公民,这提供了函数式编程的先决条件. 下面给出一个例子代码,出自一本js教程,功能是计算数组元素的平均值和标准差,先列出非函数式编程的一种写法: var data = [1,1,3,5,5]; var total = 0; for(var i = 0;i < data.length;i++)

浅谈javascript函数式编程_javascript技巧

函数式编程,属于编程范式的一种 1 函数是第一公民,可以返回值,也可以作为其他函数的参数 //console是一个函数 function con(v){ console.log(v) } // execute 也是一个函数 function execute(fn){ fn(1) } //将con函数作为参数传进execute函数 execute(con) // 1 2 接近自然语言的写法   晓池吃完饭然后就去洗澡 可以表现为eat().bathe() // 吃饭函数 function eat(

探究JavaScript函数式编程的乐趣_javascript技巧

编程范式 编程范式是一个由思考问题以及实现问题愿景的工具组成的框架.很多现代语言都是聚范式(或者说多重范式): 他们支持很多不同的编程范式,比如面向对象,元程序设计,泛函,面向过程,等等. 函数式编程范式 函数式编程就像一辆氢燃料驱动的汽车--先进的未来派,但是还没有被广泛推广.与命令式编程相反,他由一系列语句组成,这些语句用于更新执行时的全局状态.函数式编程将计算转化作表达式求值.这些表达式全由纯数学函数组成,这些数学函数都是一流的(可以被当做一般值来运用和处理),并且没有副作用. 函数式编程

使用 JavaScript 进行函数式编程 (一) 翻译_javascript技巧

编程范式 编程范式是一个由思考问题以及实现问题愿景的工具组成的框架.很多现代语言都是聚范式(或者说多重范式): 他们支持很多不同的编程范式,比如面向对象,元程序设计,泛函,面向过程,等等. 函数式编程范式 函数式编程就像一辆氢燃料驱动的汽车--先进的未来派,但是还没有被广泛推广.与命令式编程相反,他由一系列语句组成,这些语句用于更新执行时的全局状态.函数式编程将计算转化作表达式求值.这些表达式全由纯数学函数组成,这些数学函数都是一流的(可以被当做一般值来运用和处理),并且没有副作用. 函数式编程

《JavaScript函数式编程》读后感_javascript技巧

本文章记录本人在学习 函数式 中理解到的一些东西,加深记忆和并且整理记录下来,方便之后的复习. 在近期看到了<JavaScript函数式编程>这本书预售的时候就定了下来.主要目的是个人目前还是不理解什么是函数式编程.在自己学习的过程中一直听到身边的人说面向过程编程和面向对象编程,而函数式就非常少.为了自己不要落后于其他同学的脚步,故想以写笔记的方式去分享和记录自己阅读中所汲取的知识. js 和函数式编程 书中用了一句简单的话来回答了什么是函数式编程: 函数式编程通过使用函数来将值转换为抽象单元

JavaScript高阶函数的学习笔记

在Javascript中,有高阶函数的概念,因而很适合函数式编程.那神马是高阶函数呢?没有神马具体的定义,但高阶函数有两个显著的特征:.用函数做参数或返回一个函数. 函数作为参数 众所周知,函数是Javascript中的一等公民,不仅能被赋值,也能和普通变量一样,作为函数的参数. 如果你有Javascript的Web编程经验或者是一个前端开发者,就会经常碰到回调函数.在某个操作完成之后会被执行的函数就被称为回调函数.通常,回调函数都是匿名的,并作为最后一个函数传递给调用者. 由于Javascri

Reading List 2015-02

一直有个想法没有付诸实践,想做个分享知识的网站,类似 Leanote.开发者头条.GitHunt 等等的可检索的有思想的一个产品.作为尝试,在想法成型之前,先参考 http://www.dbthink.com/archives/910.http://yanjunyi.com/blog/category/discovery/ 的方式整理为知笔记中以前看到.搜集的一些文章.链接.工具等等的. 前端 http://githunt.io/ http://ohmycss.com/:简化版的bootstra