iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 20
3
Modern Web

前端常見問題攻略系列 第 20

JS - for 迴圈與 forEach 有什麼不同

  • 分享至 

  • xImage
  •  

過去,當有一個陣列的內容需要依序取值時,都會使用 for... 迴圈(for loop)的形式將值一一取出,原始碼的結構如下:

var array = ['小明', '杰倫', '漂亮阿姨', '小美']
for (var i = 0; i < array.length; i++) {
  const item = array[i];
  console.log(i, item);
}

現在,陣列執行迴圈不像過去那麼麻煩,陣列的原型中增加了許多方法可以直接運用(陣列方法可參考),其中的 forEach 基本上可以達到 for... 迴圈的所有需求(基本上用了 forEach 不太會再去使用 for loop)。

相同的結果,使用 forEach 後更容易被閱讀、理解。

array.forEach(function(item, i) {
  console.log(i, item)
});

不過實際上這兩者還是略有差異,本篇就來介紹 for 迴圈與 forEach 的那些小差別。

for loop 可能會產生全域變數

因為 JS 作用域是屬於函式作用域,而 for loop 在執行時使用 var 所建立的變數是屬於在區塊 {} 內,因此 for loop 運行時所定義的變數很常會是建立在 全域 的環境下。

以下範例來說,下列變數 i 就屬於全域的變數。

for (var i = 0; i < array.length; i++) {
  const item = array[i];
  console.log(i, item);
}
console.log(i); // 4

相對來說 forEach 使用 callback function 就不容易踩到這個雷,不過 for loop 依然可以使用 ES6 的 let, const 來解決作用域的問題。

目前主流的文字編輯器,輸入 for 後預設都會使用 let 來定義索引 i 的變數。

for (let i = 0; i < array.length; i++) {
  const item = array[i];
  console.log(i, item);
}
console.log(i) // 無法取得 i

for 可以被中斷

雖然 for loop 目前的使用率較不如 forEach,不過它可中斷運行的方式在 forEach 中是沒有的,如果迴圈中有必要停止運行,就可以使用 for loop 搭配 break

for (let i = 0; i < array.length; i++) {
  const item = array[i];
  if (i === 2) { // 執行到索引 2 就會被中斷
    break;
  }
  console.log(i, item);
}

執行到索引 2 就會被中斷,中斷後的迴圈將不會繼續運行。

https://ithelp.ithome.com.tw/upload/images/20201005/20083608AJZfClnzD1.png

並非所有陣列都能使用 forEach

JavaScript 中的陣列依據原型的不同,也有另一種分支稱為類陣列(array-like),類陣列中的原型方法與一般定義的陣列就有所不同,其中的方法就可能不包含 forEach

函式中的 arguments 就屬於類陣列,它的方法就不包含 forEach 的方法,因此它無法直接運行 forEach

function fn() {
  console.log(arguments);
  // for loop 可以正常運行
  for (let i = 0; i < arguments.length; i++) {
    const item = arguments[i];
    console.log(i, item);
  }

  // 錯誤:Uncaught TypeError: arguments.forEach is not a function
  arguments.forEach(item => {
    console.log(item);
  });
}

fn('小明', '杰倫', '漂亮阿姨', '小美');

純陣列的原型中可以找到 forEach 的方法。
https://ithelp.ithome.com.tw/upload/images/20201005/20083608qlICILZ1m6.png

arguments 類陣列中不包含 forEach 或任何的陣列方法。
https://ithelp.ithome.com.tw/upload/images/20201005/20083608TFbuunhAdW.png

類陣列可以直接使用 for loop 來運行它,如果要使用 forEach 的陣列方法也是可行,只要將類陣列透過 ES6 的 “展開” 語法轉換為純陣列即可([...])。

如以下程式碼中就透過展開將 arguments 轉變為純陣列 arg,那麼 arg 變數就可以使用 forEach 的陣列方法。

function fn() {
  const arg = [...arguments];
  arg.forEach(item => console.log(item))
}

fn('小明', '杰倫', '漂亮阿姨', '小美');

你是屬於 forEach 還是 for...loop 派呢?歡迎留言討論看看喔。


上一篇
JS 常見陣列方法
下一篇
JS async/await 系列:基礎概念篇
系列文
前端常見問題攻略30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言