数组遍历方法总结

这里记录一下,目前常用的针对数组的一些循环操作,以便以后随时翻阅。

  • 所有循环讲解主要部分均由代码展示,更简明明了。

for 循环

for 循环没啥说的,不过要记得:针对for循环,循环条件总比循环体要多执行一次。不过这个无伤大雅,一般我们都会忽略,下面看代码:

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]

for(let i = 0; i < arr.length; i++) {
    let value = arr[i];
    console.log(value);
}

# 输出结果:
# 1 2 3 4 5 6 7 8 9

for…in 循环

注意:for…in循环非常不建议用在数组上,for…in是为遍历对象属性而构建的,当然数组也可以用。

for...in循环在使用过程中要小心一点,可能会出现问题,这个下面会说到。先看 for…in 的使用:

const arr: any = [1, 2, 3, 4, 5, 6, 7, 8, 9];

for(const key in arr) {
    console.log(key);
}

# 输出结果:
# "0" "1" "2" "3" "4" "5" "6" "7" "8"

for…in 循环可以拿到数组的 key 值。针对上面的arr数组,拿到的也是key值,这个大家可以通过console.dir(arr) 来验证。

for…in使用时的bug:

这个bug的出现也具有一定的特殊性,就是我们对数组进行扩展时,使用forin循环,比如这样:

const arr: any = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// 给数组增加一个name属性
arr.name = '李明';

for(const key in arr) {
    console.log(arr[key]);
}
# 输出结果
# 1 2 3 4 5 6 7 8 9 "李明"

for(let i = 0; i < arr.length; i++) {
    console.log(arr[i])
}
# 输出结果
# 1 2 3 4 5 6 7 8 9

可以看到 forin 循环比着for循环要多输出了一个 ”李明“ ,为啥会这样呢?首先我们要知道一点:

  • for…in语句以任意顺序遍历一个对象的除Symbol以外的可枚举属性 。
  • 很不巧,我们这样给arr增加的name属性是可枚举的,forin甚至可以遍历到你给Array.prototype增加的属性与方法遍历出来。

所以这样就会导致很多意外的结果和错误。

再者,for循环为啥就不会出错呢?

  • for 循环 ,循环的是次数,for循环不关注属性。

当然我们写代码的时候 尽量要保证数组中数据类型的唯一性,比如利用Typescript:

const arr:number = [1,2,3]

arr.name = 4;

如果强行编译,还是会加上的,但是Typescript会报给我们一个错误:Property 'name' does not exist on type 'number'.

总而言之,不建议使用forin遍历数组。

for…of 循环

for…of语句在 可迭代对象(包括 ArrayMapSetStringTypedArray,arguments对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句 。

for of循环是ES6的新增方法,针对for in循环的bug,for of循环就不会有问题:

const arr:any = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.name = 12;

for(const item of arr) {
    console.log(item)
}

# 输出结果:
# 1 2 3 4 5 6 7 8 9

使用for of 循环遍历数组,其结果就是打印出数组中的每一个值,所以可以放心使用。

附加:

  • 如果使用for…of 循环时也想得到数组的下标或者是key,可以利用arr.keys()

    const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    
    for (let key of arr.keys()) {
        console.log(key)
    }
    
    # 输出结果:
    # 0 1 2 3 4 5 6 7 8
    
  • 如果使用for…of循环,既想得到key 也想得到 value ,可以利用arr.entries():

    const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    
    for (let [key, val] of arr.entries()) {
        console.log(key, val)
    }
    
    # 输出结果:
    # 0,  1 
    # 1,  2 
    # 2,  3 
    # 3,  4 
    # 4,  5 
    # 5,  6 
    # 6,  7 
    # 7,  8 
    # 8,  9 
    

forEach 循环

forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

arr.forEach((item, index, arr) => {
    console.log(item)
});

# 输出结果:
# 1 2 3 4 5 6 7 8 9

注意:

  • forEach 循环对于空数组是不会执行回调函数的。
  • forEach 循环接受三个参数,[第一参数]为数组中的每一项,[第二参数]为数组的下标,[第三个参数]为你要遍历的数组本身。第二和第三参数都是可选的。
  • forEach 循环本身不支持 continue 和 break语句的
    • 如果想实现continue效果,可以使用 return。
    • 如果要实现break效果,建议使用 every 和 some 循环。(这个后面会讲到)

map 循环

map循环返回一个经过调用函数处理后的新的数组

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const res = arr.map((item,index,arr)=>{
    return item + 1
})
console.log(res)

# 输出结果:
# [2, 3, 4, 5, 6, 7, 8, 9, 10] 

注意:

  • map 循环不会对空数组进行检测 。

  • map 循环必须 return 。

  • map 循环不会修改原数组。

  • map 循环接受三个参数,[第一参数]为数组中的每一项,[第二参数]为数组的下标,[第三个参数]为你要遍历的数组本身。第二和第三参数都是可选的。

  • map 循环会针对每一项都进行循环,如果跳过则会返回 undefined,例如:

    const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    
    const res = arr.map(item=>{
        if(item > 3) {
            return item;
        }
    })
    console.log(res)
    
    # 输出结果:
    # [undefined, undefined, undefined, 4, 5, 6, 7, 8, 9] 
    

filter 循环

filter() 循环返回一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const res = arr.filter((item,index,arr)=>{
    return item > 3;
});
console.log(res)

# 输出结果:
# [4, 5, 6, 7, 8, 9] 

注意:

  • filter 循环不会对空数组进行检测。
  • filter 循环不会改变原数组。
  • filter 循环接受三个参数,[第一参数]为数组中的每一项,[第二参数]为数组的下标,[第三个参数]为你要遍历的数组本身。第二和第三参数都是可选的。

some 循环

some 循环查找数组中任意符合条件的元素并返回boolean值,当数组中有任意元素符合条件就返回 true 否则返回 fasle

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const res = arr.some((item,index,arr)=>{
    return item > 3
})
console.log(res)

# 输出结果:
# true

注意:

  • some 循环会依次执行数组的每一个元素。
  • 如果有一个元素满足条件,则返回 true,且剩余的元素不会在执行检测 即 循环结束。
  • some 循环不会对空数组进行检测
  • some 循环不会改变原数组
  • some 循环接受三个参数,[第一参数]为数组中的每一项,[第二参数]为数组的下标,[第三个参数]为你要遍历的数组本身。第二和第三参数都是可选的。

every 循环

every 循环查找数组中所有符合条件的元素并返回boolean值,只有当数组中有所有元素都符合条件才返回 true 否则返回 fasle

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const res = arr.every((item,index,arr)=>{
    return item > 3
})
console.log(res);

# 输出结果:
# false

注意:

  • every 循环会检测数组的每一个元素
  • 如果有一个元素不满足条件,则返回false,且剩余元素不在检测 即 循环结束。
  • every 循环不会对空数组进行检测
  • every 循环不会改变原数组。
  • every 循环接受三个参数,[第一参数]为数组中的每一项,[第二参数]为数组的下标,[第三个参数]为你要遍历的数组本身。第二和第三参数都是可选的。

reduce 循环

reduce() 循环接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const res = arr.reduce((total,item,index,arr)=>{
    return total + item;
}, 0)
console.log(res);

# 输出结果:
# 45

注意:

  • reduce 循环对于空数组是不会执行回调函数的。

  • reduce 循环接受一个回调函数,和一个初始值。

    • 回调函数接受四个参数:[第一参数]为数组中的每一项累加和,[第二参数]为数组的每一项,[第三个参数]为数组的下标,[第四个参数]为你要遍历的数组本身。第三和第四参数都是可选的。

    • 初始值,即为指定第一次循环时,累加参数[total] 的值。

      • 例如 demo 中,指定初始值为 0,则reduce循环的状态为:

        [total + item]
        0
        0 + 1 = 1
        1 + 2 = 3
        3 + 3 = 6
        ...
        36 + 9 = 45
        
  • reduce 可以作为一个高阶函数,用于函数的 compose。

  • 当然reduce 的作用也不单单只作为一个累加器来用,我们还可以利用reduce的特性做其他的用途,比如数组的去重


以上就是我记录的 数组的遍历方法了 。 完结·撒花

Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐