数组里面的那些遍历方法

面试时经常被问到,记录一下数组的所有遍历方法(持续更新中…)

截止目前(2020年2月28日),数组的遍历方法共15个:

1
2
3
4
ES5:
for、forEach、every 、some、 filter、map、reduce、reduceRight、for...in
ES6:
find、findIndex、keys、values、entries、for...of

经典遍历方法

for

1
2
3
4
5
6
7
8
9
10
let arr = [1, 2, 3]
for (let i = 0; i < arr.length; i++) {
// do something
}

// 优化版写法
// 使用临时变量,将长度缓存起来,避免重复获取数组长度
for (let i = 0, len = arr.length; i < len; i++) {
// do something
}

forEach

针对每一个元素执行提供的函数。会修改原来的数组,不会返回执行结果

1
2
3
4
5
6
let arr = [1, 2, 3]
arr.forEach((currentValue, index, array) => {
// currentValue 当前元素
// index 索引
// array 正在操作的数组
})

every

测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值

ps:若收到一个空数组,此方法在一切情况下都会返回 true

1
2
3
let arr = [1, 2, 3]
console.log(arr.every((currentValue, index, array) => currentValue > 1)) // false
console.log(arr.every((currentValue, index, array) => currentValue > 0)) // true

some

测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回一个布尔值

ps:若收到一个空数组,此方法在一切情况下都会返回 false

1
2
3
let arr = [1, 2, 3]
console.log(arr.some((currentValue, index, array) => currentValue > 1)) // true
console.log(arr.some((currentValue, index, array) => currentValue > 4)) // false

filter

创建一个新数组, 返回通过所提供函数实现的测试的所有元素

ps:如果数组中没有元素符合函数测试条件,则返回空数组

1
2
3
let arr = [1, 2, 3]
console.log(arr.filte((currentValue, index, array) => currentValue > 4)) // []
console.log(arr.filter((currentValue, index, array) => currentValue > 1)) // [2, 3]

map

创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。

1
2
let arr = [1, 2, 3]
console.log(arr.map((currentValue, index, array) => currentValue * 2)) // [2, 4, 6]

reduce

对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。

1
2
3
4
5
6
7
8
9
let arr = [1, 2, 3]
let res = arr.reduce((acc, cur, idx, src) => {
// Accumulator (acc) (累计器),它是上一次调用回调时返回的累积值,如果没有return值则为undefined
// Current Value (cur) (当前值)
// Current Index (idx) (当前索引)
// Source Array (src) (源数组)
return acc + cur
})
console.log(res) // 6

reduceRight

与reduce基本相同,唯一的区别就是:reduceRight是从右向左遍历

for…in

遍历数组循环出key

1
2
3
4
5
6
7
8
9
let arr = [1, 2, 3]
for (const key in arr) {
console.log(key) // 0 1 2
}

let obj = { name: '呆呆', age: 17, job: 'coder' }
for (const key in obj) {
console.log(key)
}

es6后新增遍历方法

find

返回数组中满足提供的测试函数的第一个元素的值

ps:如果数组中没有元素符合函数测试条件,则返回undefined

1
2
3
let arr = [1, 2, 3]
console.log(arr.find((currentValue, index, array) => currentValue > 0)) // 1
console.log(arr.find((currentValue, index, array) => currentValue > 10)) // undefined

findIndex

返回数组中满足提供的测试函数的第一个元素的索引

ps:如果数组中没有元素符合函数测试条件,则返回-1

1
2
3
let arr = [1, 2, 3]
console.log(arr.findIndex((currentValue, index, array) => currentValue > 20)) // -1
console.log(arr.findIndex((currentValue, index, array) => currentValue > 0)) // 0

keys

返回一个由一个给定对象的自身可枚举属性组成的数组

1
2
3
4
5
let arr = [1, 2, 3]
console.log(Object.keys(arr)) // ["0", "1", "2"]

let arr = { name: '呆呆', age: 17, job: 'coder' }
console.log(Object.keys(arr)) //  ["name", "age", "job"]

values

返回一个给定对象自身的所有可枚举属性值的数组

1
2
3
4
5
let arr = [1, 2, 3]
console.log(Object.values(arr)) // [1, 2, 3]

let arr1 = { name: '呆呆', age: 17, job: 'coder' }
console.log(Object.values(arr1)) //  ["呆呆", 17, "coder"]

entries

返回一个给定对象自身可枚举属性的键值对数组

1
2
3
4
5
let arr = [1, 2, 3]
console.log(Object.entries(arr)) // [["0", 1],["1", 2],["2", 3]]

let arr1 = { name: '呆呆', age: 17, job: 'coder' }
console.log(Object.entries(arr1)) //  [["name", "呆呆"],["age", 17],["job", "coder"]]

for…of

遍历数组循环出value

ps:for…of不能循环普通的对象

1
2
3
4
let arr = [1, 2, 3]
for (const iterator of arr) {
console.log(iterator) // 1 2 3
}

对比

*是否修改原数组是指:在该方法的遍历中做操作,是否会影响原数组
*ps:此处的原数组值均为基本数据类型即数字、字符串数组
*pps:对象数组会修改里面的内容
*ppps:Object对象的真实数据存储在堆内存中,它在栈内存中存储的是变量名和堆内存的位置。 在循环方法里操作的obj对象,实际操作的是该对象在堆内存的地址,由于是对该地址所在的对象进行字段值修改,所以数组里的obj对象相应改变。

方法 是否修改原数组 是否有返回值 返回值内容 是否可以跳出循环
for 是 否 无 break可跳出
forEach 否 否 无 否
every 否 是 Boolean 否
some 否 是 Boolean 否
filter 否 是 Array(没有符合的过滤条件返回空数组) 否
map 否 是 Array(需要手动return,否则返回内容是undefined) 否
reduce 否 是 Any 否
reduceRight 否 是 Any 否
for…in 否 否 无 break可跳出
find 否 是 找到则返回值,否则返回undefined 否
findIndex 否 是 Number 否
keys 否 是 Array 否
values 否 是 Array 否
entries 否 是 Array 否
for…of 否 否 无 break可跳出

用途

// 单纯地遍历
Array.prototype.forEach

// 检测数组中是否有元素符合条件
Array.prototype.some

// 检测数组中是否所有元素符合条件
Array.prototype.every

// 用来将一个列表转换成另一个等长的列表
Array.prototype.map

// 用来将一个列表转换成一个值
Array.prototype.reduce

// 从列表中找出符合条件的一个元素
Array.prototype.find

// 从列表中找出符合条件的若干元素
Array.prototype.filter

// 拍平列表
Array.prototype.flat

// map 和 flat 的结合,适合用来将一个列表转换成另一个不等长的列表
Array.prototype.flatMap

哪些会修改原数组

改变数组自身内容的方法有7个:push、pop、shift、unshift、splice、sort和reverse

不会改变原数组的有:concat、join、slice、map、filter、forEach、some、every、reduce

更多api使用


数组里面的那些遍历方法
https://xypecho.github.io/2020/02/28/数组里面的那些遍历方法/
作者
很青的青蛙
发布于
2020年2月28日
许可协议