首頁>技術>

JavaScript中有多種迴圈Array的方式,你是否常常分不清他們的細微差別,和適用場景。本文將詳細梳理各間的優缺點,整理成表以便對比。| 迴圈 | 可訪問element | 可訪問index | 可迭代property | 支援中斷 | 支援await | 支援任意位置開始 || ———- | ——————- | —————- | ——————— | ———— | ————- | ———————— || for | √ | √ | × | √ | √ | √ || for in | √ | × | √ | √ | √ | × || forEach | √ | √ | × | × | × | × || for of | √ | √ | × | √ | √ | × |

for (ES1)

這個迴圈方式歷史悠久,從ECMAScript 1就被支援。

const arr = ['a', 'b', 'c'];arr.prop = 'property value';for (let index=0; index < arr.length; index++) {  const elem = arr[index];  console.log(index, elem);}// Output:// 0, 'a'// 1, 'b'// 2, 'c'

for迴圈方式通用,迭代過程可以訪問元素和當前元素下標索引,但是語法上略顯冗長。

for in (ES1)

for in 的歷史同for一樣悠久。

const arr = ['a', 'b', 'c'];arr.prop = 'property value';for (const key in arr) {  console.log(key);}// Output:// '0'// '1'// '2'// 'prop'

for in 用來迴圈陣列不是一個合適的選擇。

迭代的是屬性key,不是值由於屬性 key 是字串,迭代出的元素索引是 string,不是 number.迭代的是陣列例項上所有可列舉的屬性key,而不是陣列內元素。如果你想獲取一個物件所有的可列舉屬性(包含原型鏈上的),那麼 for in 倒是可以勝任,若僅僅是物件自身宣告的屬性,那 Object.keys 更合適。forEach (ES5) 鑑於 for 和 for-in 都不特別適合在 Arrays 上迴圈,因此在ECMAScript 5中引入了輔助方法:Array.prototype.forEach.```javascriptconst arr = [‘a’, ‘b’, ‘c’];arr.prop = ‘property value’;

arr.forEach((elem, index) => {console.log(elem, index);});// Output:// ‘a’, 0// ‘b’, 1// ‘c’, 2

這個方法很方便,它讓我們可以訪問陣列元素和陣列元素下標,而不需要做太多的事情。箭頭函式(在ES6中引入)使該方法在語法上更加優雅。`forEach` 主要確定是:- 迴圈內部不支援 `await` 操作。- 即使找到你想要的元素,也無法中斷迴圈。要實現中斷迴圈,可以使用同期引入的 `Array.prototype.same` 方法。`some` 迴圈遍歷所有 `Array` 元素,並在其回撥返回一個真值時停止。```javascriptconst arr = ['red', 'green', 'blue'];arr.some((elem, index) => {  if (index >= 2) {    return true; //結束迴圈  }  console.log(elem);  // 隱式返回假值 undefined,繼續迴圈});// Output:// 'red'// 'green'
for of (ES6)

for of 是 ECMAScript 6 新引入的語法。

const arr = ['a', 'b', 'c'];arr.prop = 'property value';for (const elem of arr) {  console.log(elem);}// Output:// 'a'// 'b'// 'c'

for of 很適合遍歷陣列:

迭代所有陣列元素內部支援 await,甚至是 ES2018 中引入的 for-await-of 語法可以使用 break 和 continue 跳出迴圈for-of 的另一個好處是,我們不僅可以遍歷陣列,還可以遍歷任何可迭代物件(例如map)const myMap = new Map() .set(false, 'no') .set(true, 'yes') ; for (const [key, value] of myMap) { console.log(key, value); } // Output: // false, 'no' // true, 'yes' 遍歷 myMap 會生成[key, value]對,對其進行解構方便直接訪問。如果你在迴圈中需要感知當前元素索引,可以透過 Array 方法 entries 返回可迭代的 [index,value]對。 和map一樣的解構直接訪問index、value:const arr = ['chocolate', 'vanilla', 'strawberry']; for (const [index, value] of arr.entries()) { console.log(index, value); } // Output: // 0, 'chocolate' // 1, 'vanilla' // 2, 'strawberry' 迴圈體內 await 測試 準備如下程式碼用於測試迴圈體內 await,getFruit 模擬遠端服務延遲返回。const fruits = ["apple", "grape", "pear"]; const sleep = (ms) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; const getFruit = (fruit) => { return sleep(2000).then((v) => fruit); }; 先看 for of, 元素之間會按預期間隔輸出。(async function(){ console.log('start'); for (fruit of fruits) { const element = await getFruit(fruit); console.log(element); } console.log('start'); })(); //3個元素 間隔2s輸出 "start" "apple" "grape" "pear" "end" 再看 forEach, 注意 forEach 呼叫後直接返回輸出 loop end, 間隔2s 後同時輸出了後面結果,並沒有按預期各個間隔輸出。(async function () { console.log("foreach loop start ...."); fruits.forEach(async value => { const element = await getFruit(value); console.log(element); }); console.log("foreach loop end ...."); })(); //同時輸出 foreach loop start .... foreach loop end .... //間隔2s 後同時輸出下面3個 apple grape pear

8
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • uniapp匯入高德地圖三維模型實現webview和頁面通訊