前言
本文925字配椭,閱讀大約需要7分鐘。
總括: forEach循環(huán)中你不知道的3件事溢吻。
- 原文地址:3 things you didn’t know about the forEach loop in JS
- 公眾號:「前端進階學習」铆铆,回復「666」建车,獲取一攬子前端技術(shù)書籍
自棄者扶不起俺夕,自強者擊不倒裳凸。
正文
你覺得你真的學會用forEach
了么贱鄙?
這是我之前對forEach
循環(huán)的理解:就是一個普通語義化之后的for
循環(huán)牲平,可以被break
,continue
,return
略步。
這篇文章將向你展示forEach
中你可能不了解的3件事。
1. return不會停止循環(huán)
你覺得下面的代碼在打印1
和2
之后會停止么嫉到?
array = [1, 2, 3, 4];
array.forEach(function (element) {
console.log(element);
if (element === 2)
return;
});
// Output: 1 2 3 4
答案是不會梦湘,上述代碼會正常打印1,2,3,4瞎颗。如果你有Java
背景,你也許會很詫異践叠,這怎么可能呢言缤?
原因是我們在forEach
函數(shù)中傳了一個回調(diào)函數(shù)嚼蚀,該回調(diào)函數(shù)的行為和普通函數(shù)一樣禁灼,我們return
操作其實就是普通函數(shù)中return
。所以并不符合我們預(yù)期將forEach
循環(huán)打斷轿曙。
注意: 除了拋出異常以外弄捕,沒有辦法中止或跳出
forEach()
循環(huán)。如果你需要中止或跳出循環(huán)导帝,forEach()
方法不是應(yīng)當使用的工具守谓。
我們將上述代碼改寫:
const array = [1, 2, 3, 4];
const callback = function(element) {
console.log(element);
if (element === 2)
return; // would this make a difference? no.
}
for (let i = 0; i < array.length; i++) {
callback(array[i]);
}
// Output: 1 2 3 4
這就是上述代碼實際的執(zhí)行思路,return
操作只作用于當前的函數(shù)您单,自然不會對for
循環(huán)產(chǎn)生影響
2. 不能break
下面的代碼你覺得會被break
掉么斋荞?
const array = [1, 2, 3, 4];
array.forEach(function(element) {
console.log(element);
if (element === 2)
break;
});
// Output: Uncaught SyntaxError: Illegal break statement
不會,甚至這行代碼都不會運行虐秦,直接報錯了平酿。
那么這段代碼如何達到我們原本想達到的效果呢?
用普通for
循環(huán)就好了:
const array = [1, 2, 3, 4];
for (let i = 0; i < array.length; i++) {
console.log(array[i]);
if (array[i] === 2)
break;
}
// Output: 1 2
3. 不能continue
下面代碼會是跳過2只打印1悦陋、3蜈彼、4嗎?
const array = [1, 2, 3, 4];
array.forEach(function (element) {
if (element === 2)
continue;
console.log(element);
});
// Output: Uncaught SyntaxError: Illegal continue statement: no surrounding iteration statement
同樣不會俺驶,和break
一樣幸逆,報錯,這行代碼之后甚至都不會運行暮现。
怎么達到預(yù)期呢?
還是使用普通的for
循環(huán)來解決:
for (let i = 0; i < array.length; i++) {
if (array[i] === 2)
continue;
console.log(array[i]);
}
// Output: 1 3 4
譯者補充
forEach
函數(shù)的實際運行原理其實是這樣的还绘,偽代碼如下:
let arr = [1, 2];
arr.forEach(function(ele) {
console.log(ele);
});
// output: 1, 2
// 上面代碼等同于
function func(ele) {
console.log(ele);
}
for (let i = 0; i < arr.length; i++) {
func(arr[i])
}
// output: 1, 2
實際上forEach
的polyfill實現(xiàn)也是這樣的,在forEach
函數(shù)中執(zhí)行一個for
循環(huán)栖袋,在for
循環(huán)里調(diào)用回調(diào)函數(shù)拍顷。
因此,像下面代碼自然不會符合預(yù)期:
let arr = [1, 2];
let sum = 0;
function add(a) {
return a;
}
arr.forEach(async function(ele) {
sum += await add(ele);
});
console.log(sum);
// Output:0
改寫如下:
let arr = [1, 2];
let sum = 0;
function add(a) {
return a;
}
for (let i = 0; i < arr.length; i++) {
sum += await add(arr[i]);
}
console.log(sum);
// Output:3
訂閱更多文章可關(guān)注「前端進階學習」栋荸,回復「666」菇怀,獲取一攬子前端技術(shù)書籍