[冬一] 函数式编程FP

79 阅读2分钟
函数式编程的概念

函数式编程是编程范式之一,可以理解为编程风格;思维模式 + 实现方法;常见的编程方式有:

  • 面向过程编程:按照步骤实现,一步一步实现功能;
  • 面向对象编程:把现实世界中的事物抽象成类和对象,通过封装、继承和多态来演示事物事件的联系;
函数式编程的本质
  • 函数式编程中的函数指的不是程序中的函数(方法),而是数学中的函数即映射关系;
  • 相同的输入始终得到相同的输出;
  • 函数式编程用来描述数据(函数)之间的映射;
// 非函数式
let a = 1;
let b = 1;
let sum = a + b;
console.log(sum)

// 函数式
function add(a, b) {
	return a + b;
}
let sum = add(1, 1)
console.log(sum)
函数是一等公民

为什么说函数是一等公民呢,是因为:1. 函数可以存储在变量中;2.函数可以作为参数;3.函数可以作为返回值;

高阶函数

概念:1.可以把函数作为参数传递给另一个函数;2.可以把函数作为另一个函数的返回结果

// 函数作为参数
function forEach(array, fn) {
 for (let index = 0; index < array.length; index++) {
  fn(array[index])
 }
}

// 函数作为返回值
function makeFn() {
 let msg = 'hello lsx'
 return function() {
  console.log(msg);
 }
}
makeFn()()

使用高阶函数的意义:

  • 可以让函数变得灵活、无需关心内部实现,只需要关注我们的目标;
  • 高阶函数是用来抽象通用的问题; 常用的高阶函数:forEach、map、filter、every、some...

手写实现部分高阶函数

// 实现map循环遍历数据并返回处理过的数组
function map(array, fn) {
 let results = []
 for(let value of array) {
  results.push(fn(value))
 }
 return results
}
// every判断数组中所有元素是否都满足条件,若有一个不满足条件则返回false,否则返回true
function every(array, fn) {
 let result = true
 for(let value of array) {
  if (!fn(value)) {
   result = false
   break    // break和continue的区别: break跳出整个循环,而continue跳出本次循环
  }
 }
 return result
}
// some数组中只要有一个满足条件即返回true,全不满足返回false
function some(array, fn) {
 let result = false
 for(let value of array) {
  if (fn(value)) {
   result = true
   break
  }
 }
 return result
}
纯函数

概念:相同的输入永远会得到相同的输出,而且没有任何可观察的副作用,类似于数学中的函数;

// 非纯函数,因为checkAge的min依赖于外部的参数
let min = 18
function checkAge(age) {
	return age > min
}

// 纯函数
function checkAge(age) {
	let min = 18
	return age > min
}

数组中的slice纯函数 splice非纯函数

  • slice: 返回数组中的指定部分,不会改变原数组;
  • splice: 对数组进行操作返回该数组,会改变原数组; 好处:
  • 可缓存;因为相同的输入永远会得到相同的输出,可以把结果缓存起来,lodash里的memoize方法;
  • 测试;
  • 并行处理;纯函数只依赖于参数,不需要访问共享的内存数据;

对于相同的输入永远会得到相同的输出,而且没有任何可观察的副作用;副作用会让一个函数变得不纯,纯函数根据相同的输入返回相同的输出,如果函数依赖于外部的状态就无法保证输出相同,就会带来副作用。副作用的来源配置文件、数据库、获取用户的输入...