­

【js】for、forEach、map數組遍歷性能比較

  • 2020 年 3 月 17 日
  • 筆記

原文鏈接:https://blog.csdn.net/qq24357165/article/details/82748976

先上結果:遍歷時間上 for循環遍歷 < for…of遍歷 < forEach遍歷 < for…in遍歷 < map遍歷。

背景

常用的數組遍歷方式有很多,如最經典的for循環

for (var i = 0; i < arr.length; i++) {}

再者有了for…in

for (var i in arr) {}

forEach

arr.forEach(function (i) {});

map

arr.map(function (i) {});

然後ES6有了更為方便的for…of

for (let i of arr) {}

此篇不考慮作用差異,僅對這些方式的性能做一次比較。

註:filter、every、some跟forEach/map相近,不常用所以本次不加入比較。

1.對比方案

本次採用最直觀的方式進行對比:通過對高數量級數組的遍歷時間進行比較。

1.1 數組arr:

let arr = [];      for (let i = 0; i < 10000000; i++) {          arr[i] = i;      }        console.log(arr);   // [0, 1, 2, 3, ... , 9999999]

1.2 對比函數:

function getAverageTime (cb) {          let _start = +new Date();            for (let k = 0; k < 20; k++) {              cb();   //  遍歷函數          }            return (+new Date() - _start) / 20 + 'ms'      }

其中cb為遍歷函數。我們通過20次求平均值的方式來推算遍歷的時間,以此作為比較依據。

2.比較

1.1 經典的for循環遍歷

getAverageTime(function () {          for (let i = 0; i < arr.length; i++) {              let item = arr[i];              // ...          }      })

結果:6.3ms

1.2 for…in遍歷

getAverageTime(function () {          for (let i in arr) {              let item = arr[i];              // ...          }      })

結果:1539.45ms

1.3 forEach遍歷

getAverageTime(function () {          arr.forEach(item => {})      });

結果:190.75ms

1.4 map遍歷

getAverageTime(function () {          arr.map(item => {})      });

結果:2014.65ms

1.5 for…of遍歷

getAverageTime(function () {          for (let item of arr) {              // ...          }      });

結果:129.5ms

*babel轉ES5後遍歷

for…of是ES6語法,所以日常頁面中基本會babel轉換,所以需要測試一下轉換後的遍歷

getAverageTime(function () {          var _iteratorNormalCompletion = true;          var _didIteratorError = false;          var _iteratorError = undefined;            try {            for (var _iterator = arr[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {              //...                var item = _step.value;            }          } catch (err) {            _didIteratorError = true;            _iteratorError = err;          } finally {            try {              if (!_iteratorNormalCompletion && _iterator.return) {                _iterator.return();              }            } finally {              if (_didIteratorError) {                throw _iteratorError;              }            }          }      });

結果:105.9ms

(是不是感覺for…of經過Babel轉換後的程式碼很詭異,有興趣可以去了解下Symbol對象,其實Symbol對象也是ES6所新加的,只是兼容比for…of好些,要兼容低版本手機的話了解一下es-symbol)

3 結果分析

通過對比可知,遍歷時間

for循環遍歷 < for...of遍歷 < forEach遍歷 < for...in遍歷 < map遍歷

3.1 *為何for… in會慢?

因為for … in語法是第一個能夠迭代對象鍵的JavaScript語句,循環對象鍵({})與在數組([])上進行循環不同,引擎會執行一些額外的工作來跟蹤已經迭代的屬性。

因此可以大致可以得出以下幾點:

  • 數據量大時,遍歷性能的差距尤為明顯;
  • for系遍歷總體性能好於forEach、map等數組方法
  • 你大爺畢竟是你大爺,性能最佳的還是經典的for循環遍歷
  • forEach性能優於map
  • for…of要兼容低版本設備的話還是算了

遍歷的性能可以作為以後開發的參考,畢竟數據量不大的時候差異可忽略不計,更多的可以根據實際作用來考慮遍歷方式,比方說for系遍歷可以break中途退出而forEach/map不行。


版權聲明:本文為CSDN部落客「MichealWayne」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/qq24357165/article/details/82748976