学习函数式编程需要非常熟悉以下概念
- 函数是一等公民
- 定义最少的无关临时变量
- 灵活使用函数作为函数的值
所以什么是函数式编程
这里我使用一个比较好理解的方式来说
函数式编程就是规范的使用函数,组合一些小函数来构建一个新函数;函数式编程是面向数学的抽象,将计算描述为一种表达式求值,一句话,函数式程序就是一个表达式。
函数式编程在前端开发中最直观的体验就是
- 流程变量赋值后就不去修改,虽然算不上声明式编程,但利于人脑理解。
- 处理容器数据结构时多用高阶函数,少用for,while和break,虽然不一定能算上函数式,但利于产生更短小易理解的代码
说人话就是尽可能不要定义let var 所有变量都是const ,不允许修改变量,子函数修改变量是很多bug的源泉
JS数组原生方法中的函数式用法
1、filter
接收一个函数创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
案例
var animals = [
{name:'apply0',species:'rabbit0'},
{name:'apply1',species:'rabbit1'},
{name:'apply2',species:'dogs'},
{name:'apply3',species:'rabbit3'},
{name:'apply4',species:'rabbit4'},
{name:'apply5',species:'rabbit5'}
]
//函数式编程
var dogs = animals.filter((x)=>x.species === 'dogs')
// 传统方式
var dogs = []
for(var i = 0; i<animals.length;i++){
if(animals[i].species === 'dogs'){
dogs.push(animals[i])
}
}
console.log(dogs)
当可能需要多个场合判断 species === 'dogs'
时,可以将其提取出为一个函数,此时的使用如下
var findSpecies = (x)=>{return x.species === 'dogs'}
var dogs = animals.filter(findSpecies)
2、map
接收一个函数,返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值
var animals = [
{name:'apply0',species:'rabbit0',code:'1120'},
{name:'apply1',species:'rabbit1',code:'1121'},
{name:'apply2',species:'dogs',code:'1122'},
{name:'apply3',species:'rabbit3',code:'1123'},
{name:'apply4',species:'rabbit4',code:'1125'},
{name:'apply5',species:'rabbit5',code:'1124'}
]
// 函数式编程
var names = animals.map((x)=>x.name)
// 传统方式
var names = []
for(var i = 0; i<animals.length;i++){
names.push(animals[i].name)
}
获取code拼接值-- 常用 输出 1120,1121,1122,1123,1125,1124
var codes = animals.map((x)=>x.code).toString()
3、 reduce
接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值
array.reduce(function(total, currentValue, currentIndex, arr), initialValue) f(初始值, 或者计算结束后的返回值;当前元素;当前元素的索引;当前元素所属的数组对象),传递给函数的初始值
任何现有方法无法满足数组操作要求都可以转化使用reduce
来满足需求
// 实现基本求和
var orders = [
{ amount: 250 },
{ amount: 34 },
{ amount: 243 },
{ amount: 76 },
{ amount: 65 },
{ amount: 45 },
{ amount: 44 },
];
// reduce
var totalAmount = orders.reduce((sum, order) => sum + order.amount, 0);
// 传统方式
var totalAmount = 0;
for (let i = 0; i < orders.length; i++) {
totalAmount += orders[i].amount;
}
console.log(totalAmount);
完成一个data.txt
文件数据的整理
mark johnwaff 80 32
mark ssdswaff830 324
nik Smaswaff 80 3
nik grff 650 34
shem shiji 90 4
var fs = require("fs");
var output = fs
.readFileSync("data.txt", "utf8")
.trim()
.split("\n")
.map((line) => line.split(" "))
.reduce((customers, line) => {
customers[line[0]] = customers[line[0]] || [];
customers[line[0]].push({
name: line[1],
price: line[2],
quantity: line[3],
});
return customers;
}, {});
console.log(JSON.stringify(output, null, 2));
输出
{
"mark johnwaff 80 32": [
{}
],
"mark ssdswaff830 324": [
{}
],
"nik Smaswaff 80 3": [
{}
],
"nik grff 650 34": [
{}
],
"shem shiji 90 4": [
{}
]
}
shensai@192 Function-code % node array.js
{
"mark": [
{
"name": "johnwaff",
"price": "80",
"quantity": "32"
},
{
"name": "ssdswaff830",
"price": "324"
}
],
"nik": [
{
"name": "Smaswaff",
"price": "80",
"quantity": "3"
},
{
"name": "grff",
"price": "650",
"quantity": "34"
}
],
"shem": [
{
"name": "shiji",
"price": "90",
"quantity": "4"
}
]
}
ES自带的高阶函数API
1、Array every()
检测数组所有元素是否全部都符合指定条件
const ages = [1,2,3,2,3,24,23,4,23,43,5,43];
const isMax = (agesArr,min) => {
return agesArr.every((e) => e > min);
};
console.log(isMax(ages,0));
2、Array some()
检测数组是否有满足指定条件的值
const ages = [1,2,3,2,3,24,23,4,23,43,5,43];
const isMax = (agesArr,min) => {
return agesArr.some((e) => e > min);
};
console.log(isMax(ages,));
3、Array sort()
对数组进行排序
const ages = [1,2,3,2,3,24,23,4,23,43,5,43];
const sortArr = (agesArr) => {
return agesArr.sort((a,b) => a-b);
};
console.log(sortArr(ages) );
总结
高效函数式编程就是把多个独立函数组合在一起使用,类似的链式调用就是常见手段