[TOC]

前言

可参照的博客:函数式编程初探 - 阮一峰的网络日志

image.png
JavaScript Function Programming[ˈproʊgræmɪŋ] JavaScript 函数式编程

函数式编程火的原因是React,因为在React里面提到的很多的“高阶函数”

课程大纲

image.png

一、函数式编程思维

image.png

现在已经有了很多的函数式编程的库,AngularJS 是运用了函数式编程的思想,React 也是在不停的践行着函数式编程的思维。

现在的大公司写 JS 有三个层次:AOP(面向切面编程) OOP(面向对象编程) 函数式编程

1. 范畴论

image.png
image.png
小红点是成员,成员之前是可以通过箭头(函数)相互转化的

2. 函数式编程基础理论

image.png
函数式编程并不是说平常写的那种将事件声明成一个方法的那种东西。
Lisp 是一个纯函数编程的语言,JavaScript 、.NET、JAVA、PHP这些语言都可以称之为类 C 语言,因为他们的写法和 C 语言非常的像,写法都大致相同。
函数式编程真正的火热是随着 React 里面的高阶函数逐步升温的。

3. 函数式编程的一些比较基本的概念

image.png

4. 函数式编程的五大特性

image.png
不能写 if else 只能写表达式。
每一个函数都要 return 一个值给下个函数来用,下个函数可以用也可以选择不用

二、函数式编程常用核心概念

image.png
image.png

1. 纯函数

image.png

  1. 项目中实际的做法

将现在的项目中的代码抽离出来编程纯函数。
可能抽离过程会相当的繁琐,但是一旦纯函数抽离成功之后会有非常多的好处:纯函数它会比较的独立,就是这个函数可以随意的去运行跟系统没有任何的关系,所以纯函数在书写的时候相对于整个系统的逻辑没有任何的影响,这就是它最大的好处了,不依赖于任何的状态。
如果你想让这个东西变得更加的强大或者是想发生一个变形的关系,你可以函数传递一个函数,函数里面去处理这个函数,然后再返回一个函数,就是这样的,写函数传函数返回函数,返回的函数可以继续往下面执行—接收函数 处理函数 返回函数,就这样慢慢的成了一个链,这样写的原因就是参照了数学的那套东西来进行的,像解题的时候都是一行一行的,第一行求出一个值再将这个值代入到下一行中进行计算再依次向下计算直到值被求出。
这个就是所谓的高阶函数,普通的函数接收一个函数让这个普通的函数可以变得更加的强大,这个就是函数式编程的一个概念。

  1. 函数式编程最重要的一点
    对于相同的输入得到的永远是相同的输出,如果相同的输入输出的结果不一样那这个函数就不是一个纯函数,因为它修改了外部的状态。
  1. 举个代码的栗子:
var xs = [1,2,3,4,5];
//Array.slice 是纯函数,因为它没有副作用,对于固定的输入,输出总是固定的
xs.slice(0,3);//[1,2,3]
xs.slice(0,3);//[1,2,3]
//Array.splice 这个就不是纯函数,因为它将原数组改变了
xs.splice(0,3);//[1,2,3]
xs.splice(0,3);//[4, 5]
  1. 函数式编程运用到项目里面之后具体的优缺点

image.png

  • 优点

image.png
lodash 是一个函数式编程典范的库。
因为函数式编程遵循着相同的输入相同的输出的原则,所以第一次执行之后在第二次执行同样的函数的时候就会用到第一次的缓存的结果就不会再次计算了,这样就可以有效降低系统的复杂度,还有很多很棒的特性比如说可缓存性。

示例的便于对上面概念进一步理解的代码片段:
image.png
上面的函数式编程代码的实现有两个好处:
首先是将代码包括到 sin 上了,降低了复杂度,还有就是在第一个计算时将参数 1 进行了缓存,第二次就不会再重新的计算了

  • 缺点

image.png
因为 checkage 函数里面依赖了外部的 min 变量,所以这个就不是纯函数了,纯函数只能依赖传入的参数

示例的优化上面截图中代码出现了问题的代码片段:
image.png
已传参的形式进行处理,这样就只依赖于参数,这样才是纯函数

2. 函数的柯里化

image.png
image.png

image.png

  1. 代码示例 ``` //柯里化之前 function add(x,y){ return x + y; }; add(1,2);//3

//柯里化之后 function addX(x){ return function(y){ return x + y; }; }; addX(1)(2);//3


> 柯里化的优势就是还可以接着再往下扩展执行,优点就是相当的灵活,扩展性超强<br />
![image.png](https://upload-images.jianshu.io/upload_images/9064013-68e09fd5cef72868.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


2. 优点

> ![image.png](https://upload-images.jianshu.io/upload_images/9064013-51fea79e8d82b148.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)



> 上例代码中 `lodash -> curry` 的用法文档<br />
[https://www.lodashjs.com/docs/4.17.5.html#curry](https://www.lodashjs.com/docs/4.17.5.html#curry)<br />
![image.png](https://upload-images.jianshu.io/upload_images/9064013-9968f173119e79b1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


- 示例代码:

```

上例代码的好处:使得扩展性更强了,而且可以将比如 filter(haveSpace) 这样的函数进行缓存方便随时进行调用

3. 函数组合

image.png

  1. 函数组合的由来

因为用到了上面的柯里化的原因,所以在项目中如果是结构较为复杂然后就一直 return 的话,看起来会非常的丑,,写出来了 “洋葱式的代码” ,一旦系统的业务逻辑复杂了起来这个东西就不行了,因此就需要用到 “函数组合” 这个东西了。