「譯」forEach循環中你不知道的3件事

前言

本文925字,閱讀大約需要7分鐘。

總括: forEach循環中你不知道的3件事。

自棄者扶不起,自強者擊不倒。

正文

你覺得你真的學會用forEach了么?

這是我之前對forEach循環的理解:就是一個普通語義化之后的for循環,可以被break,continue,return

這篇文章將向你展示forEach中你可能不了解的3件事。

1. return不會停止循環

你覺得下面的代碼在打印12之后會停止么?

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循環打斷。

MDN官方文檔:

注意: 除了拋出異常以外,沒有辦法中止或跳出 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」,獲取一攬子前端技術書籍

前端進階學習
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容