Javascript进阶——函数式编程思想
什么是函数式编程?
在学习函数式编程之前,我们先来了解一些与之相关的概念,以便于我们更好的理解函数式编程思想:
命令式编程
首先我们要明确的是什么是命令式编程,这是与函数式编程相对应的一种编程方式,在日常开发中,我们大多数使用命令式编程。命令式编程就是详细的命令机器怎么做来达到我们想要的结果。
举个例子:
有一个需求,将数组中的每一项元素乘以2,我们很容易写出以下代码(代码示例1),这就是典型的命令式编程:
let multip2=(arr)=>{
let newArr=[];
for(let i=0; i{
return regValidate(value, /^(\+|-)?\d+(\.\d+)?$/ig);
}
正确的使用纯函数可以保证更加高质量的代码,也是一种更加干净的编码方式
函数副作用
当调用函数时,除了返回函数值以外,还对主调用函数产生了附加的影响,比如更改了全局变量(函数外部的变量)或者修改了参数。
还是通过代码来说明:
// 以下代码中,test函数里改变了外部变量a的值,调用test之后,再次使用a变量就具有不确定性了
// 这就是给程序带来了副作用
let a=10;
let test=()=> a=a+1;
test();
console.log(a); //11
函数副作用会给程序设计带来不必要的麻烦,给程序带来难以查找的错误,并且降低程序的可读性
纯函数是没有副作用的。
可变性和不可变性
可变性是指一个变量创建以后可以任意修改;不可变性是指一个变量一旦创建,就永远不会发生改变,不可变性是函数式编程的核心思想。
仍然是结合代码来解释:
// 可变性,调用test方法后,data的属性值发生改变
let data={count:1};
let test=(data)=>{
data.count=2;
}
console.log(data.count);// 1
test(data);
console.log(data.count);// 2
// 我们可以通过改造test函数,使得数据不发生改变
let test=(data)=>{
// 这里也可以通过扩展属性来深拷贝{...data}, 但是扩展属性只能深拷贝数组或对象的第一层
let newData=JSON.parse(JSON.stringify(data));
newData.count=2;
}
console.log(data.count);// 1
test(data);
console.log(data.count);// 1
函数式编程
了解了前面的这些概念,我们再来看看函数式编程是怎么回事以及如何实现的吧。
“函数式编程是一种编程范式。它把计算当成是数学函数的求值,从而避免改变状态和使用可变数据。它是一种声明式的编程范式,通过表达式和声明而不是语句来编程。” 这是维基百科上对函数式编程的定义。
简单来说,就是将复杂的函数逻辑抽象出简单函数,将运算过程尽量写成一系列嵌套函数调用;将一个任务拆分成一系列最小颗粒的函数,通过组合的方式来完成任务,跟组件化的思想很类似。
与命令式相对,函数式编程本质上是一种声明式编程,我们在编码时只需要完成所需要功能的代码,无需关心其内部实现,唯一需要考虑的是在这些内部实现中是否会产生副作用。
函数式编程必须满足两个要求:
纯函数
数据不可变
我们用函数式编程思想,来将第一段代码(代码示例1)改造一下:
let arr=[1,2,3,4];
let arrMap=(arr, fn)=>{
let newArr=[];
for(let i=0; iitem * 2;
let product=arrMap(arr,multip2);
// 如果有新需求,将数组中的元素变为字符串格式
// 我们只需要添加一个tostring的函数就可满足
let tostring= item=>item.toString();
const strArr=arrMap(arr, tostring);
总结
诚然,函数式编程思想远不止如此,仍然需要更加的深入探究和大量的实践。然而即使如上述粗浅的学习心得,我们也不难发现函数式编程可以带来以下好处:
代码简洁,通过使用大量函数,重用,减少了重复的代码,提高编码效率
提高代码可靠性,得益于纯函数,不依赖、也不会改变外界的状态
易于测试维护,每一个函数都可以被看做独立单元,很有利于进行单元测试和调试,以及模块化组合
可读性强,声明式编程方式更接近自然语言
虽然清楚了函数副作用的弊端,但在开发中我们也无法完全消除函数副作用,只能尽可能的减少函数副作用:
函数入口使用参数运算,而不去修改参数
函数内不去修改函数外部的变量
运算结果通过函数返回给外部
通过“依赖注入”的方式让函数变“纯”,将依赖的变量提取出来,通过参数传给函数
发表评论 (审核通过后显示评论):