函数式编程

在前端快速发展的今天,如果不能时刻保持学习就会很快被淘汰。分享一下最近学习的函数式编程的相关知识,希望对大家有所帮助,文章有点长。每天进步一点点。

what【什么是函数式编程】

函数式编程【Functional programming】缩写【FP】,是一种编程范式,也是一种编程风格。

常见编程范式:【面向过程编程、面向对象编程、函数式编程】

1、大多数初中级前端都是在面向过程编程【按照步骤来实现】

// 面向过程编程
let num1 = 2
let num2 = 3
let sum = num1 + num2
console.log(sum)

2、面向对象编程【把现实中的事物抽象成类和对象,通过封装、继承和多态来演示不同事物之间的联系】

3、函数式编程【把现实世界事物和事物之间的联系抽象到程序世界(是对运算过程进行抽象)】

// 函数式编程
function add(n1, n2) {
    return n1 + n2
}
let sum = add(2, 3)
console.log(sum)

补充说明:函数式编程中的函数指的不是程序中的函数Function,而是数学中的函数即映射关系,例如:y=sin(x),是这种x和y的关系;

why【为什么学习函数式编程】

为什么要学习函数式编程,函数式编程重要吗?

1、React的高阶组件使用了高阶函数【高阶函数就是函数式编程的一个特性】
2、Vue3也开始拥抱函数式编程
3、函数式编程可以抛弃this
4、打包过程中可以更好的利用tree shaking过滤无用代码
5、方便测试、方便并行处理

而且有很多库可以帮助我们进行函数式开发:如 lodash、underscore、ramda、folktale等

how【如何学习函数式编程】

基础知识

函数是一等公民(First-class Function)

​ 在JS中,函数就是一个普通的对象,所以我们可以把函数像对象一样存储到变量/数组中,函数还可以作为另外一个函数的参数和返回值,甚至可以在程序运行的时候通过 new Function(‘alert(1)’)来构造一个新的函数

// 把函数赋值给变量
let fn = function () {
	console.log('Hello First-class Function')
}
fn()

// 一个示例
const BlogController = {
	index (posts) { return Views.index(posts) },
	show (post) { return Views.show(post) },
	create (attrs) { return Db.create(attrs) },
	update (post, attrs) { return Db.update(post, attrs) },
	destroy (post) { return Db.destroy(post) }
}

// 优化
const BlogController = {
	index: Views.index,
	show: Views.show,
	create: Db.create,
	update: Db.update,
	destroy: Db.destroy
}

函数是一等公民是学习高阶函数、柯里化等知识的基础

高阶函数(Higher-order function)

1、可以把函数作为参数传递给另一个函数,可以把函数作为另一个函数的返回结果

// 高阶函数 - 函数作为参数
// forEach
function forEach(array, fn) {
	for (let i = 0; i < array.length; i++) {
		fn(array[i])
	}
	
}
// const arr = [1, 2, 3, 4, 5]
// forEach(arr, item => console.log(item))

// filter
function filter(array, fn) {
	let result = []
	for (let i = 0; i < array.length; i++) {
		if(fn(array[i])) {
			result.push(array[i])
		}
	}
	return result
}
const arr = [1, 2, 3, 4, 5]
const r = filter(arr, item => item > 2)
console.log(r)
// 高阶函数 - 函数作为返回值
function makeFn() {
	let msg = 'hello'
	return function() {
		console.log(msg)
	}
}
const helloFun = makeFn()
helloFun()

// once
function once () {
	let done = false
	return function (money) {
		if (!done) {
			done = true
			console.log(`支付 ${money} 美元`)
		}
	}
}
let pay = once()
pay(5)
pay(5)

2、使用高阶函数的意义

​ 对运算过程进行抽象可以帮我们屏蔽细节,只需要关注我们的目标

​ 高阶函数是用来抽象通用的问题

// 面向过程的方式
let array = [1, 2, 3, 4]
for (let i = 0; i < array.length; i++) {
	console.log(array[i])
}
// 高阶函数
let array = [1, 2, 3, 4]
forEach(array, item => {
	console.log(item)
})

3、常用高阶函数

forEach、map、filter、every、some、find/findIndex、reduce、sort…

// map
function map(array, fn) {
	for (let value of array) {
		fn(value)
	}
}
let arr = [1, 2, 3, 4, 5]
map(arr, item => console.log(item))

// every
function every(array, fn) {
	let result = true
	for (let value of array) {
		result = fn(value)
		if (!result) {
			break
		}
	}
	console.log(result)
}
every(arr, item => item > 1)

// some
function some (array, fn) {
	let result = false
	for (let value of array) {
		result = fn(value)
		if (result) {
			break
		}
	}
	console.log(result)
}
some(arr, item => item > 4)
闭包(Closure)

1、闭包的概念:函数和其周围的状态(词法环境)的引用捆绑在一起形成闭包【可以在另一个作用域中调用一个函数的内部函数并访问到该函数的作用域中的成员】

代码见上面 【高阶函数 - 函数作为返回值】

2、闭包的本质:函数在执行的时候会放到一个执行栈上当函数执行完毕之后会从执行栈上移除,但是 堆上的作用域成员因为被外部引用不能释放,因此内部函数依然可以访问外部函数的成员

3、闭包案例

<!DOCTYPE html>
<html>
<head>
	<title>闭包案例</title>
</head>
<body>
	<script type="text/javascript">
		// 生成计算数字的多少次幂的函数
		function makePower(power) {
			return function(number) {
				return Math.pow(number, power)
			}
		}
		const power2 = makePower(2)
		const power3 = makePower(3)
		console.log(power2(2))
		console.log(power2(3))
		console.log(power3(2))
	</script>
</body>
</html>

通过断点调试,可以清楚的看到闭包发生的位置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T4lV1M5M-1616041069681)(C:\Users\71705\AppData\Roaming\Typora\typora-user-images\image-20210313124634062.png)]

纯函数

纯函数的概念

1、纯函数:相同的输入永远会得到相同的输出,而且没有任何可观察的副作用

​ 纯函数就类似数学中的函数(用来描述输入和输出之间的关系),y = f(x)

img

2、lodash 是一个纯函数的功能库,提供了对数组、数字、对象、字符串、函数等操作的一些方法

​ 数组中的的 slice是纯函数【 返回数组中的指定部分,不会改变原数组】 ,数组的 splice 是不纯的函数【对数组进行操作返回该数组,会改变原数组】

let numbers = [1, 2, 3, 4, 5]

// 纯函数
numbers.slice(0, 3)
// => [1, 2, 3]
numbers.slice(0, 3)
// => [1, 2, 3]
numbers.slice(0, 3)
// => [1, 2, 3]

// 不纯的函数
numbers.splice(0, 3)
// => [1, 2, 3]
numbers.splice(0, 3)
// => [4, 5]
numbers.splice(0, 3)
// => []

​ lodash常用的方法:first、last、toUpper、reverve、each、includes、find、findIndex等等

​ 使用lodash前需要先初始化一个package.json并安装lodash【npm init -y;npm i lodash】

// lodash 常用方法
// first、last、toUpper、reverve、each、includes、find、findIndex
const _ = require('lodash')

let arr = ['jack', 'jone', 'mack', 'tom']
console.log(_.first(arr))
console.log(_.last(arr))
console.log(_.toUpper(_.first(arr)))
console.log(_.reverse(arr))
let r = _.each(arr, (item, index) => {
	console.log(index, item)
})
console.log(r)

3、函数式编程不会保留计算中间的结果,所以变量是不可变的(无状态的)

4、我们可以把一个函数的执行结果交给另一个函数去处理

纯函数的好处

1、可缓存

​ 因为纯函数对相同的输入始终有相同的结果,所以可以把纯函数的结果缓存起来

// lodash的缓存函数 memoize
const _ = require('lodash')
function getArea (r) {
	console.log(r)
	return Math.PI * r * r
}
// let getAreaWithMemory = _.memoize(getArea)
// console.log(getAreaWithMemory(4))
// console.log(getAreaWithMemory(4))
// console.log(getAreaWithMemory(4))

// 模拟 memoize 函数
function memorize (fn) {
	let cache = {}
	return function() {
		const key 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React是一个用于构建用户界面的JavaScript库。它采用了组件化的开发方式,使得开发者可以将界面拆分成独立的、可复用的组件。在React中,函数式编程是一种常见的编程范式,它强调使用纯函数来构建应用。 函数式编程是一种编程范式,它将计算视为数学函数的求值过程。在函数式编程中,函数被视为一等公民,可以作为参数传递给其他函数,也可以作为返回值返回。函数式编程强调不可变性和无副作用,即函数的执行不会改变外部状态。 在React中,函数式编程被广泛应用于组件的开发。使用函数式编程的方式,我们可以将组件定义为纯函数,接收一些输入参数(称为props),并返回一个描述组件界面的React元素。这种方式使得组件的开发更加简洁、可测试和可维护。 函数式编程在React中的一些特点包括: 1. 纯函数:组件函数应该是纯函数,即相同的输入应该始终产生相同的输出,而且不应该有副作用。 2. 无状态组件:函数式组件通常是无状态的,即它们不会保存任何状态信息,只依赖于传入的props进行渲染。 3. 高阶组件:函数式编程可以使用高阶组件(Higher-Order Components)来增强组件的功能,例如添加共享的逻辑或状态管理。 总结一下,React中的函数式编程是一种将组件定义为纯函数的开发方式,它强调不可变性和无副作用,使得组件的开发更加简洁、可测试和可维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值