Array.forEach的那些小秘密
在写地图的聚合功能里,单个聚合点下
- 包含一个故障点,则聚合圈为红色;
- 不包含故障点但含离线点,则聚合圈为黄色
- 不包含故障点和离线点,则聚合圈为绿色
因为地图不包含属性的过滤,只能我们去循环了。但是地图点位包含几万个,每个点位用去循环,跳出,效果很差。
师傅:
你要做优化,你写 forEach ,break跳不出来
我:
😶 ??? forEach 跳不出来?
迅速找找度娘,扒forEach
的那些小秘密
forEach
forEach 的基础了解
- 句法
forEach((element, index, array) => { ... } )
forEach 本质上接收的是一个匿名函数
,无法像语句一样,使用 break 进行跳转。看到这里,小伙伴们不禁说, return return
~ 那我们就来试一试吧
const arr = [1, 2, 3, 4]
arr.forEach(n => {
if(n === 2) {
return false
}
console.log(n)
})
输出为134
,跳出当次的循环了,小伙伴,好厉害!!那么问题来了
【问】 那我们如何让他 停止接下来的循环?毕竟布噜的开题的优化是要跳过接下来的循环
如何停止循环
- 抛出异常,跳出循环
let k = null
const arr = [1, 2, 3, 4]
try {
arr.forEach(n => {
if (n === 2) {
throw Error()
}
k = n
})
} catch (e) {}
console.log(k)
最终输出为 1
2. forEach()
除了抛出异常之外,没有其他方法可以停止或中断循环。如果您需要这种行为,那么该forEach()
方法就是错误的工具。那我们有什么替换方案呢?
插一嘴🧐 ,从这里也能看出,forEach的本质是 对数组的每个元素进行一次函数内的操作
替换方案
- 一个简单的
for
循环
var i = 0;
for (;;) {
if (i > 3) break; // here 退出循环
console.log(i);
i++;
}
- 一对
for...of
和for...
in循环 Array.prototype.every()
const isBelowThreshold = (currentValue) => currentValue < 40;
const array1 = [1, 30, 39, 29, 10, 13];
console.log(array1.every(isBelowThreshold));
Array.prototype.some()
Array.prototype.find()
Array.prototype.findIndex()
- 数组方法:
every()
、some()
、find()
和findIndex()
使用返回真值的谓词测试数组元素以确定是否需要进一步迭代。
大数据下,为什么forEach 会比for 循环慢得多
这个还与 ES
中的实现有关
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(callback, thisArg) {
var T, k;
if (this == null) {
throw new TypeError(' this is null or not defined');
}
var O = Object(this);
var len = O.length >>> 0;
if (typeof callback !== "function") {
throw new TypeError(callback + ' is not a function');
}
if (arguments.length > 1) {
T = thisArg;
}
k = 0;
while (k < len) {
var kValue;
if (k in O) {
kValue = O[k];
callback.call(T, kValue, k, O);
}
k++;
}
};
}
forEach
在实现中对调用者本身进行了一系列的检查,不如for
循环简单callback.call(T, kValue, k, O);
在一定程度上也会消耗性能
好奇的小伙伴,可以使用console.profile
和 console.profileEnd
进行性能测试
【tip】
在进行数组较大 for 循环的时候,可以将长度另外提取出来,避免重复获取数组长度