前言
本文章源自《JavaScript知识小册》专栏,感兴趣的话还请关注点赞收藏.
上一篇文章:《JavaScript解构赋值》
下一篇文章:《JavaScript中的伪数组》
花样百出的数组遍历
在JS中遍历数组的方式有很多,本文仅做知识索引,方便需要用时可以查找
for循环
首先是最简单的for...i++
let arr = [1,2,3]
for (let i = 0; i < arr.length; i++) {
console.log(arr[i])
}
输出1 2 3
forEach()
arr.forEach((elem,index,array) => {
console.log(elem, index, array)
})
forEach
相当于是定义一个函数来逐个遍历数组,这个函数有3个参数,elem
表示当前元素,index
表示当前元素对应的下标,array
表示当前遍历的数组本身。
forEach
和for...i++
还有个区别在于,forEach
中无法使用break
或continue
来中断循环。
map()
forEach
只是对数组元素的循环,map
除了遍历数组中每个元素,还可以根据回调操作将数组中的元素做处理,形成新的返回值,最后构建出新的数组。
let arr = [1, 2, 3]
let result = arr.map((value) => {
value = `seq ${value}`
return value
})
console.log(result)
输出 ["seq 1", "seq 2", "seq 3"]
,原本是number类型的数组,通过map
构建为新的string类型的数组
filter()
filter
除了遍历数组中的每个元素,还可以根据特定条件对数组中的元素进行筛选,只有符合条件的元素才会被选中,最后形成新的数组并返回
let result1 = arr.filter((value) => {
return value === 2
})
console.log(result1)
输出[2]
some()
some
则是遍历数组中是否有符合条件的元素,只要有一个元素符合条件,就会返回true
,否则返回false
let isHave = arr.some((value) => {
return value === 2
})
输出true
every()
every
作用跟some
一样,但是比some
更苛刻,需要数组中每个元素都符合条件,才返回true
,否则返回false
let isAllHave = arr.every((value) => {
return value === 2
})
输出false
reduce()
reduce
相当于接收一个函数作为累加器
let arr = [1,2,3]
let sum = arr.reduce((prev,cur,index, array) => {
return prev + cur
}, 0)
console.log('reduce', sum)
输出6
,相当于1+2+3=6。reduce
方法有两个参数,第一个参数是一个函数,第二个参数是初始值。因为reduce
重点是做一个累加使用,而且仅仅是为了计算出arr
数组里所有元素的总和,所以这里初始值设置为0。也就是相当于0+1+2+3=6。而第一个参数则表示数组元素累加时所回调的函数。
prev
表示上一次回调的时候所对应的返回值,因为初始值是0,所以prev
一开始等于0
cur
表示当前正在处理的数组元素
index
表示当前正在处理的数组元素对应的索引
array
表示源数组
return prev + cur
其实就表示了将上一次累加的结果,和本次正在处理的数组元素做一个累加,最后返回。也可以根据业务逻辑做一些特殊处理,比如当前数组中元素是奇数的话,则不累加,直接return prev
,是偶数的话才return prev + cur
reduce
也可以不仅仅是做累加操作,还可以是计算出数组中最大值
let max = arr.reduce((prev, cur) => {
return Math.max(prev, cur)
})
console.log(max)
输出3
,原理也很简单,做数组元素累加时,prev
是上一次累加的结果,但也可以不做累加,而是把prev
看做是上一次数组元素,cur
看做是当前正在处理的数组元素,那么只需要在每次遍历数组元素时,取prev
和cur
两者最大值并返回,本次返回的最大值,将作为下一次遍历时的prev
,然后与cur
再作比较,最后就能得到数组中最大值。
reduce
也可以做数组去重用
let arr = [1,2,2,3,3]
let set = arr.reduce((prev, cur) => {
prev.indexOf(cur) === -1 && prev.push(cur)
return prev
}, [])
console.log(set)
输出[1,2,3]
,同样是会循环数组所有元素,但这里把prev
初始值设为了[]
,cur
是当前正处理的数组元素,每次循环回调(prev,cur) => {}
时,都检查一遍prev
是否已包含了当前数组元素,不是的话才把cur
添加到prev
中。
for...in... [不建议]
let arr = [1,2,3]
for (let index in arr) {
console.log(index, arr[index])
}
输出0 1
1 2
2 3
遍历数组看起来没什么问题,但是要注意的是for...in...
不仅会遍历出数组的值,同时也会遍历出prototyp下自定义的方法
比如在Array.prototype
上加上print
方法
Array.prototype.print = () => {
console.log('print')
}
再执行上边的代码,输出则不止是
0 1
1 2
2 3
同时也会把print()
给打印出来
print ƒ () { console.log('print'); }
所以其实不建议使用for...in...
遍历数组
find()
find
是返回数组中第一个满足条件的元素
let arr
let findRes = arr.find((value) => {
return value === 2
})
console.log('find', findRes)
输出find 2
findIndex()
findIndex
是返回数组中第一个满足条件的元素的下标
let arr
let findRes = arr.findIndex((value) => {
return value === 2
})
console.log('findIndex', findRes)
输出findIndex 2
for...of
for...of
跟for...in
一样可以用来遍历数组,但是for...of
不会像for...in...
那样把prototype
的自定义方法也遍历出来
let arr = [1,2,3]
for (const item of arr) {
console.log(item)
}
输出1 2 3
values()
values
这个方法其实是返回数组中的所有值,然后我们可以基于返回的所有值进行遍历
let arr = [1, 2, 3]
for (const val of arr.values()) {
console.log(val)
}
输出1 2 3
,与上边for...of
结果无异
keys()
key
这个方法则相当于返回数组中的所有值的下标,然后我们遍历的话,则变成了在遍历下标
let arr = [1, 2, 3]
for (const val of arr.values()) {
console.log(val)
}
输出0 1 2
entries()
entries
则相当于是keys
和values
结合,我们遍历的时候既可以取得数组元素下标,也可以取得数组元素
for (const [index, item] of arr.entries()){
console.log(index, item)
}
输出0 1
1 2
2 3