今天我们来看看一个JavaScript中关于数组遍历方法之一的forEach方法。一在网上查forEach有啥特点,回答的内容大多的如下
1.forEach不能return指定的内容,就算你return了指定内容,最终返回的也是undefined
2.不能在forEach中使用break或者continue关键字
诚然这些是对的,但是为什么呢?这就比较少讲了。
今天我们参考了MDN中关于forEach的代码,来看看这是为什么。
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(callback, thisArg) {
var T, k;
//this表示调用forEach的对象,比如[1,2,3].forEach(()=>{}),this就是[1,2,3]
if (this == null) {
throw new TypeError(' this is null or not defined');
}
//通过Object(this)得到一个对象,Object([1,2,3]) => [1,2,3]
var O = Object(this);
//O.length>>>0表示得到一个>=0的length
var len = O.length >>> 0;
if (typeof callback !== "function") {
throw new TypeError(callback + ' is not a function');
}
// 5. If thisArg was supplied, let T be thisArg; else let
// T be undefined.
if (arguments.length > 1) {
T = thisArg;
}
// 6. Let k be 0
k = 0;
// 7. Repeat, while k < len
while (k < len) {
var kValue;
//k表示当前对象的索引值(下标,而非元素的值)
if (k in O) {
kValue = O[k];
//调用传入的回调函数
callback.call(T, kValue, k, O);
}
k++;
}
// 8. return undefined
};
}
forEach中之所以有最前面说的那些限制是因为用户的回调函数是在一个while循环中执行的。请看下面的代码。
const fn = (n)=>{
console.log(n)
return undefined;
}
const ff = ()=>{
for(let i = 0;i<3;i++){
fn(i);
}
return 'a'
}
const result = ff();
console.log('result',result)
ff就相当于forEach,fn就相当于forEach中的回调函数,一个循环产生了多个callback函数调用,如果用户在callback中使用return了,只是在当前产生的回调函数中使用return,没有跳出ff这个函数,只是跳出了fn这个函数,所以return指定值是没有效果的。
为什么forEach的返回值是undefined,因为forEach没有指定返回值,或者是return undefined或者是return void 0;注意void 0等同于undefined。
const fn = (n)=>{
console.log(n)
break;//没有使用循环,这里肯定会报错的
return undefined;
}
const ff = ()=>{
for(let i = 0;i<3;i++){
fn(i);
}
return 'a'
}
const result = ff();
console.log('result',result)
那为什么forEach中不能使用break或者continue呢?因为你在写break或者continue时,这两个关键字是在fn中,fn中明显没有for循环这类能够支持使用这两个关键字的代码,当然会报错啦。
那我们该如何跳出forEach呢?
可以通过抛出异常来跳出forEach
const arr = [1,2,3]
arr.forEach(item=>{
if(item===2){
throw new Error('break')
}
console.log(item)
})
这样子就完成了跳出forEach的要求。