专栏名称: JavaScript
面向JavaScript爱好人员提供:前端最新资讯、原创内容、JavaScript、HTML5、Ajax、jQuery、Node.js等一系列教程和经验分享。
目录
相关文章推荐
51好读  ›  专栏  ›  JavaScript

你有必要知道的函数式编程

JavaScript  · 公众号  · Javascript  · 2017-04-19 10:59

正文

请到「今天看啥」查看全文


return x + y ;

}

add ( 1 , 2 ) // 3

// 柯里化之后

function addX ( y ) {

return function ( x ) {

return x + y ;

};

}

addX ( 2 )( 1 ) // 3

有了柯里化以后,我们就能做到,所有函数只接受一个参数。后文的内容除非另有说明,都默认函数只有一个参数,就是所要处理的那个值。

三、函子

函数不仅可以用于同一个范畴之中值的转换,还可以用于将一个范畴转成另一个范畴。这就涉及到了函子(Functor)。

3.1 函子的概念

函子是函数式编程里面最重要的数据类型,也是基本的运算单位和功能单位。
它首先是一种范畴,也就是说,是一个容器,包含了值和变形关系。比较特殊的是,它的变形关系可以依次作用于每一个值,将当前容器变形成另一个容器。

上图中,左侧的圆圈就是一个函子,表示人名的范畴。外部传入函数f,会转成右边表示早餐的范畴。
下面是一张更一般的图。

上图中,函数f完成值的转换(a到b),将它传入函子,就可以实现范畴的转换(Fa到Fb)。

3.2 函子的代码实现

任何具有map方法的数据结构,都可以当作函子的实现。

class Functor {

 constructor(val) {

   this.val = val;

 }

 

 map(f) {

   return new Functor(f(this.val));

 }

}

上面代码中,Functor是一个函子,它的map方法接受函数f作为参数,然后返回一个新的函子,里面包含的值是被f处理过的(f(this.val))。
一般约定,函子的标志就是容器具有map方法。该方法将容器里面的每一个值,映射到另一个容器。
下面是一些用法的示例。

(new Functor(2)).map(function (two) {

 return two + 2;

});

// Functor(4)

 

(new Functor('flamethrowers')).map(function(s) {

 return s.toUpperCase();

});

// Functor('FLAMETHROWERS')

 

(new Functor('bombs')).map(_.concat(' away')).map(_.prop('length'));

// Functor(10)

上面的例子说明,函数式编程里面的运算,都是通过函子完成,即运算不直接针对值,而是针对这个值的容器—-函子。函子本身具有对外接口(map方法),各种函数就是运算符,通过接口接入容器,引发容器里面的值的变形。
因此,学习函数式编程,实际上就是学习函子的各种运算。由于可以把运算方法封装在函子里面,所以又衍生出各种不同类型的函子,有多少种运算,就有多少种函子。函数式编程就变成了运用不同的函子,解决实际问题。

四、of 方法

你可能注意到了,上面生成新的函子的时候,用了new命令。这实在太不像函数式编程了,因为new命令是面向对象编程的标志。
函数式编程一般约定,函子有一个of方法,用来生成新的容器。
下面就用of方法替换掉new。

Functor.of = function(val) {

 return new Functor(val);

};

然后,前面的例子就可以改成下面这样。

 

Functor.of(2).map(function (two) {

 return two







请到「今天看啥」查看全文