【转】用函数式特性优化你的 for 循环
用函数式特性优化你的for循环
本教程源于用函数式特性优化你的 for 循环!
本教程适用于JS
主要作用是将复杂的处理逻辑拆分到不同的函数中,需对语言中的关键字有较为清晰的认识
前置代码
const list = [
{
name: 'jason',
score: 21,
human: true,
},
{
name: 'Crystal',
score: 18,
human: true,
},
{
name: 'Bob',
score: 81,
human: false,
},
]
原始代码
const process = (list) => {
// 定义了将在后续使用的全局变量
const fileterdItems = []
let totalScore = 0
// 遍历并传入list数组
for (let i = 0; i < list.length; i ++) {
// 筛选list数组中human为真的对象
if (list[i].human) {
// score字段中的值被累加在函数中定义的全局变量totalScore中
totalScore += list[i].score
// 将这些对象保存在filteredItems所引用的数组中
filteredItems.push({
list[i],
// 添加了名为updated的字段,用于表示对象内容的更新时间
updated: new Date()
})
}
}
// 打印totalScore和filteredItems的值
console.log(filteredItems, totalScore)
}
process(list)
process函数存在两个问题
- 业务逻辑不清晰
- 依赖于多个外部变量
修改后代码
const process = (list) => {
const filteredItems = list
// filter函数筛选出list中human字段为真的对象
.filter(i => i.human)
// map函数为筛选出的对象添加update字段
.map(i => ({
...i, updated: new Date(),
}))
const totalScore = filteredItems
// reduce函数对filteredItems中所有对象上的score字段值做累加
.reduce((p, i) => p += i.score, 0)
console.log(filteredItems,totalScore)
}
process(list)
在修改后的代码中,使用filter、map、reduce三个函数完成了相同的处理逻辑
这么做有两个优点:
- 业务逻辑内聚在不同的函数内
- 不依赖于外部变量
函数的解释
map
常用于进行数组的转换与映射
接收一个回调函数,并在给定数组中的每一个元素上调用该函数,将所得到的一系列返回值作为新的数组元素返回
var arr = [1,2,3,4,5,6]
arr.map(function (element, index, arr){
return element * 2
})
element——当前正在遍历的数组元素 index——该元素从0开始的索引值 arr——当前正在遍历的数组
arr = [2,4,6,8,10,12]
filter
主要用于对给定的数组中的元素进行筛选
与map类似,但只有当回调函数返回一个真值结果时,相对应的数组元素才会被包含在过滤结果中
arr.filter(function (element, index, arr) {
return element % 2 === 0
})
arr = [2,4,6]
reduce
对给定数组进行遍历,在遍历过程中,进行针对某个结果的累积过程
arr.reduce(function (prev, element, index, arr) {
return prev + element
})
prev——回调函数在迭代上一个元素时的返回结果,若当前迭代的元素为第一个元素,则回调函数的第一个参数值为reduce函数通过第二个参数指定的初始值
在这里为0
21
结语
JS中的map/filter/reduce函数借鉴于函数式语言中的同名操作符,他们具有更清晰的操作意图,在正确使用下,可保证原数组的不可变性(Immutability),减少产生bug的概率