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 表现正常)
posted @ 2022-03-24 20:46  IslandZzzz  阅读(68)  评论(0编辑  收藏  举报