导语:
-
为什么要学习函数编程以及什么是函数式编程
-
函数式编程的特性(纯函数,柯里化,函数组合等)
-
函数式编程的应用场景
-
函数式编程库Lodash
-
函数式编程随着React的流行受到越来越多的关注
-
vue3也开始拥抱函数式编程
-
函数式编程可以抛弃this
-
打包过程中可以更好的利用tree shaking过滤无用代码
-
方便测试和并行处理
-
多库协助开发:Lodash,underscore,ramda
什么是函数式编程
函数式编程(Functional Programming FP),是编程的一种范式。
而函数式编程中的函数不是指程序中的函数方法,而是把数学中的函数映射关系运用到了程序中。
-
高阶函数:可以把函数作为参数传递给另一个函数,也可以把函数作为另一个函数的返回结果
// forEach function forEach(array,fn) { for (let i=0; i<array.length;i++){ fn(array[i]) } } // filter function filter (array, fn) { let results = [] for (let i=0;i<array.length;i++){ if (fn(array[i])){ results.push(array[i]) } } return results } // 函数作为返回值 function hello () { let msg = \'hello Function\' return function () { console.log(msg) } } const fn = hello() fn() function once(fn) { let done = false return function () { if (!done) { done = true return fn.apply(this,arguments) } } } let pay = once(function(money){ console.log(`支付:${money}RBM`) }) pay(5) pay(5) pay(5) pay(5) // 只会支付一次 支付了:5 RMB // 面向过程的方式 let array = [1,2,3,4] for (let i = 0; i<array.length;i++){ console.log(array[i]) } // 高阶函数 forEach(array,item => { console.log(item) }) let r = filter(array,item => { return item % 2 === 0 }) 使用高阶函数的意义:抽象可以帮我们摒弃细节,只关注目标,高阶函数式用来抽象通用的问题 常用的高阶函数:forEach,map,filter,every,some,find/findIndex,reduce,sort...... const map = (array,fn) => { let results = [] for(const value of array) { results.push(fn(value)) } return results } const every = (array,fn) => { let result = true for (const value of array){ result = fn(value) if (!result) { break } } return result } const some = (array,fn) =>{ let result = false for (const value of array){ result = fn(value) if (result) { break } } return result }
-
闭包: 函数执行的时候会放到一个执行栈上,执行完就会从执行栈移除,但是堆上的作用域成员因为应用不能释放,因此内部函数依然可以访问外部函数的成员
// 第一个数是基本工资,第二个数是绩效工资 function makeSalary (x) { return function(y) { return x + y } } let salaryLevel1 = makeSalary(1500) let salaryLevel2 = makeSalary(2500)
-
纯函数:
-
相同的输入永远会得到相同的输出,而且没有副作用(lodash是一个纯函数的功能库,提供了对数组,数字,对象,字符串,函数等操作的一些方法slice-纯函数,splice-不纯的函数)
-
纯函数的好处:可缓存,可测试,没有副作用
-
-
柯里化
-
当一个函数用多个参数的时候,先传递一部分参数调用它,然后返回一个新的函数接收剩余的参数,返回结果
-
可以降低函数的颗粒度
-
对函数参数的‘缓存’
-
可以把多元函数转换成一元函数,可以组合使用函数产生强大的功能
-
-
函数组合:纯函数和柯里化很容易出现洋葱代码
-
函数就像数据的管道,函数组合就是把这些管道链接起来,让数据穿过多个管道形成最终结果
-
-
涵子:一个特殊的容器,通过一个普通的对象来实现,该对象具有map方法,map方法可以运行一个函数对值进行处理(变形关系)
// 一个容器包裹一个值 class Container { static of (value) { return new Container(value) } constructor (value) { this._value = value } } // map 方法,传入变形关系,将容器里的每一个值映射到另一个容器 map (fn) { return Container.of(fn(this._value)) } // 测试 Container.of(3).map(x => x + 2).map(x => x*x)
总结:函数式编程的运算不直接操作值,而是由涵子完成,涵子就式一个实现了map契约的对象,函子就像一个盒子,这个盒子封装了一个值,想要处理盒子中的值我们需要给盒子的map方法传递一个处理值的函数(纯函数),由这个函数来对值进行处理,最终map方法返回一个包含新值的盒子(函子)
MayBe函子的作用就是可以对外部的空值做处理(控制副作用在允许的范围)
Either函子:类似于if...else... 的处理,可以用来处理异常处理
IO函子:把函数作为值来处理
Pointed函子:实现了of静态方法的函子,of 是未了避免使用new来创建对象,of方法用来把值放到上下文context