在之前的文章中,我们学习了许多关于函数本质的知识,那么我们接下来,就应该思考函数的应用问题: 在实际开发中,我们需要用函数来做些什么? 我们可以使用函数这些特性来玩一些什么高级的东西? 我们要如何使用函数才能让我们的代码更加清晰直观?
函数式编程,就是我们接下来要思考的函数应用问题。
封装是一个非常重要的概念。这个概念在我们的代码中随处可见。
对于函数来说,封装是将一堆代码放在函数中,当我们想要执行这一堆代码的时候,不用重复编写,而只需要调用一下这个函数,就能够做到同样的事情。
因此,将一堆代码封装成为一个函数,会极大的降低我们的代码量。
例如一个简单的例子,我们要计算两个数字的平均值,那么我们会如下计算
1const a = 102const b = 2034const sum = a + b5const average = sum / 2
将其封装成为一个函数之后
1// 封装2function getAverage(num1, num2) {3const sum = num1 + num24return sum / 25}678// 使用9getAverage(10, 20)
当然,如果只是代码的堆砌,封装没有任何难度。而真正需要我们深入思考的核心重点,还在于,要明白,封装,其实是对公共逻辑的提炼。
例如,我们要计算一个数组中,所有子项的和。
如果我们仅仅只是计算一个简单数组的子项之和时,会直接将子项加起来就可以了
1const arr = [1, 2]2const sum = arr[0] + arr[1]
但是如果数组的子项数量很多呢?这样的方式就变得非常不合适,因此当我们想要针对所有的数组,来实现计算子项之和时,就必须要提炼出来公共的逻辑。
10// 封装20function mergeArr(arr) {30const result = 0;40for (let i = 0; i++; i < arr.length) {50result += arr[i];60}7080return result;90}1011// 使用12mergeArr([1, 2])13mergeArr([1, 2, 3, 4, 5])
如果我们在使用函数时,没有去总结过封装的提炼思维,那么你的函数可能会非常糟糕,甚至自缚手脚,出现一些无法预知的 bug。
函数式编程是一种编程范式,是一个非常好用的封装思维。
现在已知有一个数组,需求是找出数组中的所有数字,并将这些数组放在一个新的数组里。
const arr = [1, 3, 'a', 'd', 5, 8, '9']
如果不考虑封装的问题,很容易实现
1const arr = [1, 3, 'a', 'd', 5, 8, '9']2const newArr = []34arr.forEach(item => {5if (typeof item === 'number') {6newArr.push(item)7}8})
如果封装只是代码的堆砌,也能够做到
10const arr = [1, 3, 'a', 'd', 5, 8, '9']2030function getNumbers() {40const newArr = []5060arr.forEach(item => {70if (typeof item === 'number') {80newArr.push(item)90}10})11return newArr12}1314const newArr = getNumbers()
显然,这并不是很好的方式,这样的方式仅仅只能满足单个数组这样的需求,那如果我们还需要从其他数组中也找出来所有的数字项呢?又只能重新写。
因此,我们要从多个需求场景中,将共同的逻辑提炼出来封装一个函数。
10// 将目标数组作为参数传入到函数中20function getNumbers(arr) {30const newArr = []4050arr.forEach(item => {60if (typeof item === 'number') {70newArr.push(item)80}90})10return newArr11}121314// 使用时15const arr = [1, 3, 'a', 'd', 5, 8, '9']16const numArr = getNumbers(arr) // 无论有多少个数组,都能够做到同样的需求
封装好之后,我们在使用时,只需要关心该函数有什么功能,需要什么参数,而不需要过多的关心函数的内部实现,就能够顺利的将函数运用起来。从整个项目来说,这样的代码会简洁许多,维护起来也会更加简单。
当然,对于这些简单的案例,许多同学在做封装时,自然的就使用了这样的策略,但是因为没有提炼的意识,在遇到复杂场景时,就容易写出低质量的函数。这里需要我们结合更多的实践,持续的强化我们的提炼思维。
在现实中这种思维也非常常见。
我们点外卖,只需要在 app 中下单,然后等待外卖小哥把外卖送到我们手里就行。我们不用关注我们点的餐是如何做出来的,也不用关注外卖小哥是如何送过来的,这种更加关心结果的思维方式,便是函数式编程的运用。
OK,通过一些简单的案例了解了函数式编程之后,下一章我们将会更加详细的解读函数式编程思维。