You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

75 lines
2.5 KiB

2 years ago
# 结合语义化、可读性和程序性能选择遍历方法
在实际开发中,经常会用到遍历方法对集合进行判断,过滤,筛选等.
对于ES5年代,我们大多依托基于lodash封装的`BI.each,BI.map,BI.some,BI.filter`方法,ES6时代,原生的`forEach,map,filter`等方法经常被使用
我们这里分析一下如何结合语义化、可读性和性能选择合适的遍历方法
## BI.xxx和原生的遍历方法有什么区别?
1. BI.xxx方法保留了JQuery年代遍历方法的使用习惯,迭代调用的函数参数顺序为`(index,value)`,因此现在大多情况下,我们推荐使用原生遍历方法
2. BI.each方法可以遍历对象,原生javascript并未提供相应方法,`for...in`和`for..of`都无法同时获取key-value
## 语义化可读性的原则
1. 如果你需要将数组按照某种规则映射为另一个数组,就应该用map
2. 如果你需要进行简单的遍历,用forEach
3. 如果你需要提前中断迭代,那么使用some或every
4. 如果你需要过滤出符合条件的项,用filter
5. 如果你需要遍历数组累计计算出某个结果,那可以用reduce
6. 如果你需要先根据条件过滤,再按照规则映射为新数组,那就用filter加一个map
实际场景举例
```javascript
// 利用some提前中断的特性减少遍历
const arr = [1, 3, 4, 7];
const hasEven = arr.some(v => v % 2 === 0);
const allOdd = arr.every(v => v % 2 === 1);
```
```javascript
// 迭代累计结果,两种实现并无高低之分,但求简单易懂
const arr = [1, 3, 4, 7];
const allCount1 = arr.reduce((previousValue, currentValue) => previousValue + currentValue, 0);
let allCount2 = 0;
arr.forEach(v => allCount2 += v);
```
## 既要有性能意识,又无需过度追求性能
绝大多数情况,我们无需考虑究竟是`forEach`更快,还是`for...in`更快,我们的主要目标是写出清晰,稳定,可持续的代码.
与此同时,我们有尽量避免一些显而易见的代码缺陷,一个常见的误区是在遍历中重复进行额外的遍历.
对于在循环遍历中可以保持不变的信息,可以在遍历之外提前计算好再使用
```javascript
const arr1 = [
{
name: "xiaoming",
age: 17
}, {
name: "dashan",
age: 28
}
];
const arr2 = [14, 25, 36, 17];
// 每次都要进行map
arr2.forEach(v => {
if (arr1.map(j => j.age).includes(v)) {
console.log(true);
}
});
// 对不变数据进行预先提取
const ages = arr1.map(j => j.age);
arr2.forEach(v => {
if (ages.includes(v)) {
console.log(true);
}
});
```