遍历数组有很多方法, 最简单的便是 for 循环, 另外还有 forEach、map、filter、some、every、reduce 等 ;
每种方法面向的场景是不一样的, 先讲一下使用, 性能嘛, 最后再看
for
for 循环是最基础的一种循环方式
1 | // 一般把长度先缓存, 避免重复获取, 无需多言 |
for
循环可以通过break
、return
等语句提前终止for
并没有块级作用域
当遇到return
语句时 , 包含此for
循环的方法会终止
1 | const gg = () => { |
字符串同样有 length 属性, 所以可以遍历字符串
forEach
一般用于对数组每一项进行修改, 没有返回值
1 | arr.forEach((_) => { |
由于break
, continue
只能在循环中使用, 而 forEach 回调function
是函数
很明显不可以
通过break
, continue
等中断循环
但是可以
通过return
结束本次循环
1 | ;[1, 2, 3, 4, 5].forEach((_) => { |
如果要我非要终止循环
呢, 也不是不行, 不过我暂时只能想到抛异常的方法
1 | try { |
Set
, Map
原型中包含forEach
方法, 所以可以用于遍历Set
, Map
, 并不需要 Array.forEach.call / apply
的方式去做
1 | Set.prototype.forEach // ƒ forEach() { [native code] } |
那么 Set 和 Map 调用 forEach 打印的 index, value 都是什么呢
1 | new Set(['one', 'two', 'three', NaN, NaN]).forEach((value, index, set) => { |
map
一般是对每个元素进行一些处理, 并返回新的数组
1 | arr.map((el, index) => { |
Set
, Map
没有该方法
常见用法
1 | const arr = [ |
filter / find
filter 用来查找符合条件的元素集合
find 找到第一个符合条件的元素并返回, 找到后不再往下遍历
every / some
这两个方法更多地用在测试数组的个性every
测试数组内的所有元素是否都能通过某个指定函数的测试, 最终返回布尔值, 只要有一个元素不通过则终止循环并返回 false
1 | const arr = [10, 30, 8, 2, 6] |
some
测试是否至少有一个元素通过由提供的函数实现的测试, 最终返回布尔值, 只要有一个元素通过则终止循环并返回 true
1 | const arr = [1, 2, 7, 11, 6] |
for in
for in 循环可以遍历字符串、对象、数组,不能遍历 Set/Map, 并且只能拿到可枚举的(enumerable)属性
需要注意的是, in
可以拿到原型上的属性
1 | let obj = { |
还有, 如果给数组加上属性, 也会被迭代出来
1 | const arr = [1, 2, 3] |
因为迭代的顺序是依赖于执行环境的,所以数组遍历不一定按次序访问元素。因此当迭代访问顺序很重要的数组时,最好用整数索引去进行 for 循环
for of
遍历 Array 可以采用下标循环,遍历 Map 和 Set 就无法使用下标。
为了统一集合类型,ES6 标准引入了新的 iterable 类型,Array、Map 和 Set 都部署了 Symbol.iterable 迭代器
for of 循环不仅支持数组、大多数伪数组对象,也支持字符串遍历,此外还支持 Map 和 Set 对象遍历
1 | let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]); |
区别
for…in 语句以原始插入顺序迭代对象的可枚举属性, 拿到的是键
for…of 语句遍历可迭代对象定义要迭代的数据, 拿到的是值