函数式编程探索(一) -《JS函数式编程指南》读后感

《JS函数式编程指南》使用 JavaScript讲述了函数式编程的基本思想,函数式编程有很多优点,比如简洁,消除"副作用"等等。同时它是来源数学理论,可以达到更高的抽象度。

介绍

函数式编程也叫面向函数编程,是编程范式的一种,它其实出现得很早,理论基础起源于上个世纪30年代数学界的lambda演算,属于范畴论,最早运用这一思想的编程语言是上世纪50年代的Lisp语言,这门语言在黑客圈极具传奇色彩。

另一种更为大家知道的编程范式就是大名鼎鼎的面向对象编程(当然,面向“对象”编程,是程序猿的梦想之一)。十年之前,我们接触到的编程教材、技术文章,讲述的几乎都是面向对象编程,编程不使用接口、类、继承,都不好意思说自己会编程。

函数式编程思想近几年越来越为大家接受和推崇,两大主流语言相继增加了支持函数式编程的特性:

Java8新增了Lambda表达式,同时增加了相关应用场景的支持,如Stream流式处理;

JavaScript也在ES6增加了Lambda表达式,也增加了相关应用场景的支持,如Arraymap, fliter, reduce操作。同时,JavaScript的三大框架之一React,今年新增了Hooks特性,支持有状态函数组件,从而完全可以替代类组件。

从大的趋势来看,各大主流语言逐渐趋于支持多种范式,如JavaScript同时也增加了面向对象的特性:类和继承。

函数式编程的特点

函数是一等公民

这是函数式编程一个基本条件,这里并不是说函数有什么优先权,而是:函数和其它数据类型一样,可以赋值给变量、可以作为参数传递、可以作为返回值等等。

根据上面的特点,我们还可以引申出来一些概念:

  • 函数嵌套
  • 闭包
  • 高阶函数

这些JS开发者都很熟悉,也会经常用到,等后面再回过头看看这些特性在函数式编程里面有什么使用场景。

代码示例:

// 嵌套函数,返回函数
function regexCheck(reg) {
  return function(str) {
    return reg.test(str)
  }
}

// 高阶函数
regexCheck(/^(130|131)\d{8}$/)('13012341234')

使用表达式,而不是语句

表达式的特点是:它是一个单纯的运算过程,完成后总是会有运算结果。最常见的表达式就是运算表达式,比如:

const a = 10
const b = a * 10 + 10

函数式编程里的表达式,其实就是把函数当作普通变量来使用:

// 参数函数,返回函数
function ifNot(func) {
    return function(x) {
        return !func(x)
    }
}

// 函数组合
const isHtmlTag = regexCheck(/<\/?\S+>/)
;['hello world', ''].filter(ifNot(isHtmlTag))

把函数当作变量一样来运算,代码可以变得很简洁灵活(后续还会接触更多的)。

没有副作用

这里的"副作用"就是Side Effect,指的就是:函数运行过程中,产生了运算以外的其他结果,比如:修改了全局变量、向数据库写入了数据、发起了网络请求等等。

函数式编程为什么要消除“副作用”,经验丰富的程序员一定知道,系统复杂性和Bug很多时候就是因"副作用"而起:

  • 一个全局变量,很多地方都去使用和修改它,你将很难保证它没有被错误地使用。如果还涉及到了多线程,那就大大增加了系统复杂性,你去面试后端岗位,高并发是考察你能力的最重要的点。
  • 向数据库写入了数据和发起了网络请求一样,永远是系统中的炸弹,你不知道它什么时候就出现你没有预料到的状况。

当然,我们也不能完全避免副作用,我们要做的是控制它,状态管理器Redux中就有effects概念,React Hooks里面也有effect hook,目的都是隔离“副作用”。

消除"副作用"有一个常见的方案:不改变状态,即函数调用返回新的值,如:

const serials = ['10', '20', '30']
// 下面的运算不会改变前面的变量
const serialsOpts = serials.concat(['40', '50']).join('/')

引用透明

引用透明其实就是前面特性的衍生特性,说的就是:使用相同的参数调用函数,每次都会得到相同的结果。 我们完全可以用结果代替这个函数表达式,所以叫引用透明。

当一个函数不依赖外部变量和状态时,它就可以满足引用透明,这样的函数我们也叫它纯函数

它的好处很多:

  • 很容易的理解和推导程序。
  • 我们还可以很容易地构建测试程序,因为它的运算逻辑是单纯、稳定的。
  • 可以任意地并行执行。

总结

函数编程起源于数学的范畴论,理论相当抽象,我还是个初学者,本篇简单介绍了函数式编程的历史和现状,讲述了函数式编程的基本特点。后续我还会继续学习和记录函数式编程的相关理论、常见设计模式和它们的应用。

欢迎交流

个人读书公众号,欢迎交流!

你可能感兴趣的:(函数式编程,javascript)