为什么现在还要学函数式编程
函数式编程不是用函数来编程,也不是传统的面向过程编程,主旨在于将复杂的函数复合成简单的函数,运算过程尽量写成一系列嵌套的函数调用。要注意区分用函数编程和函数式编程是不同的。
函数式编程的思想是对运算过程进行抽象,也就是把运算过程抽象成函数,然后在任何地方都可以去重用这些函数。
函数式编程随着react的流行越来越受到关注
vue3也开始拥抱函数式编程(vue3对vue2做了很大的重构,而且越来越偏向函数式)
函数式编程可以抛弃this
打包过程中可以更好的利用tree shaking过滤无用代码
方便测试,方便并行处理
有很多库可以帮我们进行函数式开发:lodash,underscore,ramda
函数式编程的时候一定会有一些函数,这些函数后续可以无数次的重用,所以函数式编程的一个好处就是,可以让代码进行重用,而且在函数式编程的过程中,抽象出来的函数都是细粒度的,那这些函数将来可以重新去组合成功能更强大的函数。
函数是一等公民(First-class Function)
在编程语言中,一等公民可以作为函数参数,可以作为函数返回值,也可以赋值给变量。
正因为在大部分主流语言里,函数不是一等公民,才需要强调在某些语言里「函数是一等公民」
函数可以赋值给变量
函数可以作为参数
函数可以作为返回值
高阶函数((Higher-order function)
定义:高阶函数是对其他函数进行操作的函数,它接收函数作为参数(参数列表中包含函数) 或 将函数作为返回值输出。
思想:函数式编程的思想是对运算过程进行抽象,也就是把运算过程抽象成函数,然后在任何地方都可以去重用这些函数。
抽象可以帮我们屏蔽实现的细节,我们以后在调用这些函数的时候只需要关注我们的目标就可以了,那高阶函数就是帮我们抽象这些通用的运算过程。
函数作为参数
在js中,数组的forEach,map,filter,every,some,find, findIndex, reduce, sort等都是高阶函数,因为他们都接收一个函数做为参数。
举一个简单的例子:以前我在业务开发中需要遍历数组然后去执行一些操作,就会去写一个循环来做这样一件事,然后每次都要去定义循环变量,判断循环索引。写循环真的自己都烦,可是也每次都去写
// 面向过程方式
let array = [1, 2, 3, 4];
for (let i = 0; i < array.length; i++) {
console.log(array[i]);
}
但其实我是知道数组这个对象是有map,forEach方法可以来代替我每次去写循环。就是不用,真蠢
Array的forEach函数实现,
这里的forEach就是对通用问题的一个抽象,forEach函数帮我们把循环的过程抽象成一个函数,我们在使用的时候不需要关注循环的具体实现,也就是不需要关注循环的细节,也不需要变量去控制,我们只需要知道forEach函数可以帮我们完成循环就ok 了。我们可以看到使用forEach要比for循环简洁很多,所以我们使用函数式编程还有一个好处就是使代码更简洁。
// 高阶函数
let array = [1, 2, 3, 4];
array.forEach(item => {
console.log(item);
})
那接下来我们自己实现一个forEach高阶函数 (也很简单啦哈哈)
var arr = [1,2,3,4,5,6];
function forEach(arr,fn){
for(let i=0;i<arr.length;i++){
fn(arr[i],i);
};
};
forEach(arr,function(item,index){
console.log(item,index)
})
那接下来我们自己实现一个filter高阶函数
var arr = [1,2,3,4,5,6];
function filter(arr,fn){
let result = [];
for(let i=0;i<arr.length;i++){
if(fn(arr[i],i)){
result.push(arr[i])
}
};
return result;
};
let result = filter(arr,function(item,index){
if( item%2==0 ){
return true;
}
})
console.log(result)
函数作为返回值
就是让一个函数去生成一个函数
函数作为返回值的基本语法
function makeFn(){
let msg = "Higher-order function";
return function(){
console.log(msg);
}
}
let fn = makeFn();
fn();
那么它有什么样的好处呢,我们来写一个once函数 (在jquery中有一个once函数,它的作用是给一个dom元素注入事件这个事件只会执行一次)
在loDash中也有一个once函数,作用是对作为参数传入的函数只执行一次,我们模拟一下lodash中的once函数
function once(fn){
let done = false;
return function(){
if(!done){
done = true;
fn.call(this,...arguments);
}
}
};
const pay = once(function(money){
console.log(`支付了${money}RMB`)
});
pay(10);
pay(20);
pay(30);