前言
本文925字,閱讀大約需要7分鐘。
總括: forEach循環中你不知道的3件事。
- 原文地址:3 things you didn’t know about the forEach loop in JS
- 公眾號:「前端進階學習」,回復「666」,獲取一攬子前端技術書籍
自棄者扶不起,自強者擊不倒。
正文
你覺得你真的學會用forEach
了么?
這是我之前對forEach
循環的理解:就是一個普通語義化之后的for
循環,可以被break
,continue
,return
。
這篇文章將向你展示forEach
中你可能不了解的3件事。
1. return不會停止循環
你覺得下面的代碼在打印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
函數中傳了一個回調函數,該回調函數的行為和普通函數一樣,我們return
操作其實就是普通函數中return
。所以并不符合我們預期將forEach
循環打斷。
注意: 除了拋出異常以外,沒有辦法中止或跳出
forEach()
循環。如果你需要中止或跳出循環,forEach()
方法不是應當使用的工具。
我們將上述代碼改寫:
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
這就是上述代碼實際的執行思路,return
操作只作用于當前的函數,自然不會對for
循環產生影響
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
循環就好了:
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
一樣,報錯,這行代碼之后甚至都不會運行。
怎么達到預期呢?
還是使用普通的for
循環來解決:
for (let i = 0; i < array.length; i++) {
if (array[i] === 2)
continue;
console.log(array[i]);
}
// Output: 1 3 4
譯者補充
forEach
函數的實際運行原理其實是這樣的,偽代碼如下:
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實現也是這樣的,在forEach
函數中執行一個for
循環,在for
循環里調用回調函數。
因此,像下面代碼自然不會符合預期:
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
訂閱更多文章可關注「前端進階學習」,回復「666」,獲取一攬子前端技術書籍
前端進階學習