1. 程式人生 > 其它 >js 幾種 for 迴圈的區別

js 幾種 for 迴圈的區別

1 js 幾種 for 迴圈的區別

測試 loop 型別:

for
forEach
forOf
forin
forof
Object.keys

測試維度:

1. 是否可訪問非索引的屬性
2. 是否會訪問到empty元素
3. 是否可中斷迴圈
4. 是否可訪問原型屬性
5. 是否可訪問不可列舉屬性
6. 是否支援正常非同步

測試用例

const arr = ['a', 'b', 'c']
arr.props = 'test arr'
arr.__proto__.protoKey = 'proto key'
Object.defineProperty(arr, 'hiddenKey', {
  value: 'hidden key',
  writable: false,
  configurable: false,
  enumerable: false
})

2 for

ESMAScript1 就存在,相容性較強。但語法冗長,不優雅

  1. 是否可訪問非索引的屬性 否
  2. 是否可訪問 empty 元素 是,列印輸出 undefined
  3. 是否可訪問原型鏈屬性 不可
  4. 是否可訪問不可列舉屬性 不可
  5. 是否可中斷迴圈 是,continue 中斷本次,break 中斷本趟,return 中斷函式執行
  6. 是否支援非同步 是,await 表現正常
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]) // a b c
}

delete arr[1] // empty
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]) // a undefined c
}

const asyncFn = () => Promise.resolve(1)
;(async () => {
  for (let i = 0; i < arr.length; i++) {
    console.log('step1')
    console.log(await asyncFn())
    console.log('step2')
  }
})()
/* 
    step1
    1
    step2   
    ...
*/

3 forEach

  1. 是否可訪問非索引的屬性 否
  2. 是否可訪問 empty 元素 否,不會執行 empty 的回撥
  3. 是否可訪問原型鏈屬性 不可
  4. 是否可訪問不可列舉屬性 不可
  5. 是否可中斷迴圈 不可,只能使用 return 返回本次回撥
  6. 是否支援非同步 否,await 表現異常
const asyncFn = () => Promise.resolve(1)
arr.forEach(async (v, i) => {
  console.log('begin',v)
  console.log(await asyncFn())
  console.log('after',v)
})
/* 
begin a
begin b
begin c
1
after a
1
after b
1
after c
*/

4 forof

  1. 是否可訪問非索引的屬性 否
  2. 是否可訪問 empty 元素 是,列印輸出 undefined
  3. 是否可訪問原型鏈屬性 不可
  4. 是否可訪問不可列舉屬性 不可
  5. 是否可中斷迴圈 是,continue 中斷本次,break 中斷本趟,return 中斷函式執行
  6. 是否支援非同步 是,await 表現正常
for (const v of arr) {
  console.log(v) // a b c
}

for (const v of arr) {
  if (v === 'b') continue // // break; return;也可
  console.log(v) // a c
}

;(async () => {
  for (const v of arr) {
    console.log('step1')
    console.log(await asyncFn())
    console.log('step2')
  }
  /* 
    step1
    1
    step2
    ...
  */
})()

5 forin

可以訪問原型鏈上的可列舉屬性,如果不需要此功能,考慮結合 hasOwnProperty 或者改用 Object.keys()

  1. 是否可訪問非索引的屬性 是
  2. 是否可訪問 empty 元素 不可
  3. 是否可訪問原型鏈屬性 可
  4. 是否可訪問不可列舉屬性 不可
  5. 是否可中斷迴圈 是,continue 中斷本次,break 中斷本趟,return 中斷函式執行
  6. 是否支援非同步 是,await 表現正常
for (const key in arr) {
  console.log(key, arr[key])
  /* 
        0
        2
        props
        protoKey
   */
}

;(async () => {
  for (const key in arr) {
    console.log('begin')
    console.log(await asyncFn())
    console.log('after')
  }
  /* 
    begin
    1
    after
    ...
  */
})()

6 總結

型別 是否可訪問非索引的屬性 是否會訪問到 empty 元素 是否可訪問原型鏈屬性 是否可訪問不可列舉屬性 是否可中斷迴圈 是否支援非同步
for 是,列印輸出 undefined 是(continue,break,return) 是(await 表現正常)
forEach 否,不會執行 empty 元素的回撥 否,表現異常
forof 是,列印輸出 undefined 是(continue,break,return) 是(await 表現正常)
forin 是,列印輸出 undefined 是(continue,break,return) 是(await 表現正常)