函数式编程的认识
前端小菜鸡一枚,第一次写文章分享自己所学的知识,也想记录自己学习的点滴。如有写的不对的地方欢迎指出哈~ 如果文章的内容对你有所帮助麻烦给个赞哈。作为一名人前端小白,自己FP函数的理解肯定不能够完全到位,后续如果对函数式编程又新的见解会持续更新该文章的~
前言:
我们为什么要学习函数式编程?
现在前端的主流框架 React,Vue3 都是函数式编程,这使我们不得不对函数式编程有学习。
既然说到函数式编程是一种编程范式,这也就意味着不他像是一种框架,你只要认真学完之后就能学会。读完这篇文章可能更多的是给你带来的收益是一种启发。函数式编程是需要我们不断的在工作中将知识进行实践,需要时间的沉淀与积累。
函数式编程是编程中的一种范式,与面向对象这种类型编程的风格(思想)是并列关系。
(编程范式: 编程思想或是说是编程中的一种编程风格)
- 函数式编程:将现实世界中的事物与事物之间的 联系 抽象到程序世界(抽象其运算过程)
- 程序的本质:根据输入通过某种运算获得相应的输出,程序开发过程中会涉及很多有输入和输出的函数
- 函数式编程的函数是指数学中的函数例如:** y=sin(x)** ,x和y的映射关系
- x->f(联系、映射)->y,y=f(x)
// 求工资的例子 基础工资 + 绩效工资
function add(a,b) {
return a + b
}
函数式编程前置知识
函数是一等公民(First-class Function)
引用mdn中对函数是一等公民的定义:
当一门编程语言的函数可以被当作变量一样用时,则称这门语言拥有头等函数。例如,在这门语言中,函数可以被当作参数传递给其他函数,可以作为另一个函数的返回值,还可以被赋值给一个变量。
MDN 函数是一等公民
// 函数(本身就是对象)像对象使用的例子
// 不论我们以哪种方式声明函数,其都是 Function 的实例
// 可以通过 new 关键字来声明 (ps: 在js高级程序设计中讲到不建议这样声明函数)
const fn = new Function()
console.log(fn) // [Function: anonymous]
// 像对象一样拥有自己的实例属性
const sum = (a, b) => a + b
console.log(sum.length) // 2
// 可以存储到数组对象中
const obj = {
sum
}
const arr = [sum]
console.log(obj.sum(1, 2)) // 3
console.log(arr[0](3, 5)) // 8
// 作为参数
const callback = (pre,cur) => pre + cur
console.log([1,2,3,4].reduce(callback,0))
// 作为返回值
function doOnce(fn) {
let isDone = false
return function (money) {
if (isDone) return
isDone = true
fn(money)
}
}
const pay = doOnce(money => {
console.log(`支付了${
money}$`)
})
// 多次调用pay仅执行一次打印 支付了100$
pay(100)
pay(100)
pay(100)
总结为:
- 函数可以作为变量使用
- 函数可以作为另一个函数的参数
- 函数可以作为返回值
当我第一次得知这个概念的时候,非常困惑不知为什么称函数为一等公民?函数其实跟跟普通对象的功能一样嘛,唯一不同的是它可以调用(可,额,这就可以成为一等公民 ???)
不过也不用太纠结,只是个概念而已。我们只需要记住上面总结的话就行了,这是接下来我们要学习 高阶函数和函数柯里化的基础。
高阶函数
高阶函数听起来很高大上有没有~ 但是我们在日常开发中经常会用到。比如数组中常用的方法: forEach,map,filter,find,some等等,这些都是属于高阶函数。
高阶函数的定义:
- 函数可以作为令一个函数的参数
- 函数可以作为另外一个函数的返回值
工作中常用到的高阶函数有:
- forEach
- map
- filter
- every
- some
- find/findIndex
- reduce
- sort
- …
使用高阶函数的意义:
- 屏蔽细节,只关注目标
- 将通用性问题进行抽象
const arr1 = [1, 2, 3, 4]
const arr2 = [11, 12, 13, 14]
// 现在我们有两个需求,找出第一个数组中大于2的数,以及第二个数组中小于13的数,你会怎么做?
// 面向过程式的编程
// 第一个需求
let res1 = []
for (let i = 0; i < arr1.length; i++) {
if (arr1[i] > 2) {
res.push(arr[i])
}
}
// 第二个需求
let res2 = []
for (let i = 0; i < arr2.length; i++) {
if (arr2[i] < 13) {
res2.push(arr[i])
}
}
// 使用高阶函数
function myFilter(arr, fn) {
let res = []
for (let i = 0; i < arr.length; i++) {
if (fn(arr[i], i, arr)) {
res.push(arr[i])
}
}
return res
}
const res1 = myFilter(arr1, itme => item > 2)
const res2 = myFilter(arr2, item => item < 13)
// 1. 对比面向过程式的实现需求,使用高阶函数可以帮助我们屏蔽细节(如使用for循环),只关注我们的目标(拿到arr1数组大于2的数).
// 2. 可以抽象通用性问题,如当前这个例子 过滤数组中的元素。
闭包
挖个坑,笔者接下来会写有关闭包的博客,请大家持续关注。
函数式编程基础
纯函数
纯函数的概念: