这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战
| 方法 | 简洁程度 | 对 break/continue 的支持 | 备注 |
|---|---|---|---|
for | 低 | ✔ | 用于遍历数组,遍历过程受控,可以通过 break 和 continue 实现对遍历的控制 |
forEach | 高 | ✖ | ES5 新增。用于遍历数组,遍历过程不受控,会遍历完所有元素 |
every | -- | ✖ | ES5 新增。用于遍历数组,遍历过程受控,通过设置函数返回值的真假,实现和 break、continue 相同的效果 |
for in | -- | ✔ | ES3 中就存在了。为 object 设计的,数组属于 object,也能用,但有瑕疵。遍历出的元素的索引是 string 类型的,而不是 number 类型。for in 会把自定义属性也遍历出来。 |
for of | -- | ES6 新增。用于遍历自定义的数据结构(该自定义的数据结构不是数组,也不是 object),同时也可以遍历数组。通过修改默认的遍历机制,配合 for of 的使用,使得 for of 的功能非常强大。 |
1. for
const arr = [1, 2, 3, 4, 5]
for (var i = 0; i < arr.length; i++) {
console.log(arr[i])
}
/* 结果:
1
2
3
4
5
*/
const arr = [1, 2, 3, 4, 5]
for (var i = 0; i < arr.length; i++) {
if (arr[i] === 2) {
break // for 循环中 break 有效
}
console.log(arr[i])
}
/* 结果:
1
*/
const arr = [1, 2, 3, 4, 5]
for (var i = 0; i < arr.length; i++) {
if (arr[i] === 2) {
continue // for 循环中 continue 有效
}
console.log(arr[i])
}
/* 结果:
1
3
4
5
*/
2. forEach
const arr = [1, 2, 3, 4, 5]
arr.forEach(function (item) {
console.log(item)
})
/* 结果:
1
2
3
4
5
*/
const arr = [1, 2, 3, 4, 5]
arr.forEach(function (item) {
if (item === 2) {
break // 报错:Unsyntactic break
}
console.log(item)
})
const arr = [1, 2, 3, 4, 5]
arr.forEach(function (item) {
if (item === 2) {
continue // 报错:Unsyntactic continue
}
console.log(item)
})
相比于 for,forEach 的写法更加简洁,但是它不支持 break 和 continue,它所遍历的是从头到尾的每个元素。
拓展:
// 声明一个长度为 5 的数组 array
let array = Array(5)
// 给数组的所有元素赋值为 1
array.forEach(function (item) {
item = 1
})
console.log(array)
/* 结果:
(5) [empty × 5]
*/
可见,forEach 不能给数组元素赋值。
3. every
特性:every 遍历数组时,是否继续往下遍历,取决于函数的返回值,返回值为 true 时继续遍历,返回值为 false 时结束遍历,默认的返回值为 false。
const arr = [1, 2, 3, 4, 5]
arr.every(function (item) {
console.log(item)
// 函数返回值默认为 false,因此遍历出第一个元素后就结束遍历
})
/* 结果:
1
*/
const arr = [1, 2, 3, 4, 5]
arr.every(function (item) {
console.log(item)
return true // 函数返回值为 true,表示继续遍历
})
/* 结果:
1
2
3
4
5
*/
上面代码块中函数返回 true 时,every 也能遍历所有元素了,看上去和 forEach 的行为一样。你可能会问,既然在这个时候 every 和 forEach 的行为很像了,那为什么还要新增 every 这个 API 呢?因为我们上面说过,forEach 有弊端,forEach 是不受控的,如果你用 forEach,它必须从头遍历到尾,它不支持 break 和 continue,而 every 虽然也不支持 break 和 continue,但 every 中可以实现和 break、continue 相同的效果,如何实现呢?其实,every 能不能向下遍历取决于函数的返回值,想要达到break的效果,可以使用return false,想要达到continue的效果,可以使用return true,所以说 every 是受控的。
const arr = [1, 2, 3, 4, 5]
arr.every(function (item) {
if (item === 2) {
return false // 结束函数的执行,不再继续遍历,相当于实现了 break 的效果
}
console.log(item)
return true
})
/* 结果:
1
*/
const arr = [1, 2, 3, 4, 5]
arr.every(function (item) {
if (item === 2) {
// 不做处理,相当于实现了 continue 的效果
} else {
console.log(item)
}
return true
})
/* 结果:
1
3
4
5
*/
4. for in
for in 是为可遍历的 object 做遍历的,而不是为数组,只是数组也属于 object,并且数组是可遍历的,所以也能用 for in 遍历,但是用 for in 遍历数组会有瑕疵。
const arr = [1, 2, 3, 4, 5]
for (var index in arr) {
console.log(index, arr[index])
}
/* 结果:
0 1
1 2
2 3
3 4
4 5
*/
const arr = [1, 2, 3, 4, 5]
arr.pro = 8 // 为 arr 数组添加属性 pro(arr 是数组,数组是对象,对象上可以挂属性)
for (var index in arr) {
console.log(index, arr[index])
}
/* 结果:
0 1
1 2
2 3
3 4
4 5
pro 8
*/
可见,数组的索引不一定是数字,也可以是字符串。用 for in 遍历数组,如果数组上挂载了属性,也会被遍历出来,导致和我们的预期不同,这就是用 for in 遍历数组的瑕疵。
const arr = [1, 2, 3, 4, 5]
arr.pro = 8
for (var index in arr) { // 使用 for in 遍历,元素的索引是 string 类型的,而不是 number 类型。即这里的 index 是字符串类型
if (index == 2) { // 左边 index 是 string 类型,右边 2 是 number 类型(注意:== 只比较值,不比较类型;而 === 既比较类型,也比较值,只要类型不同就返回 false)
break // for in 中支持 break
}
console.log(index, arr[index])
}
/* 结果:
0 1
1 2
*/
const arr = [1, 2, 3, 4, 5]
arr.pro = 8
for (var index in arr) {
if (index == 2) {
continue // for in 中支持 continue
}
console.log(index, arr[index])
}
/* 结果:
0 1
1 2
3 4
4 5
pro 8
*/
上面的 if 条件判断中,如果想使用 ===,可以将 index == 2 换成 index * 1 === 2 或者 +index === 2 或者 index === '2'。
字符串中只有数字时,可以通过乘 1 或在字符串前加个加号将字符串转换为 number 类型:
var test = '00023' // 字符串中只有数字
var test1 = test * 1 // 乘以 1 转换成 number 类型
var test2 = +test // 前面加个加号转换成 number 类型
console.log(test, typeof (test)) // 00023 string
console.log(test1, typeof (test1)) // 23 "number"
console.log(test2, typeof (test2)) // 23 "number"
5. for of
for of 用于遍历自定义的数据结构(该自定义的数据结构不是数组,也不是 object),同时也可以遍历数组。
5.1 遍历数组
const arr = [1, 2, 3, 4, 5]
for (let item of arr) {
console.log(item)
}
/* 结果:
1
2
3
4
5
*/
5.2 遍历自定义的数据结构
// 假设有 A、B、C 三类商品,每类商品下有不同价格的商品,现就价格进行如下定义:
const Price = {
A: [2.3, 1.5, 4.5],
B: [3, 5],
C: [0.8, 0.5, 1.2]
}
如果想要找出每类商品中的最低价,该怎么实现呢?
我们先用 for in 遍历
for (let key in Price) {
console.log(key, Price[key])
}
/* 结果:
A (3) [2.3, 1.5, 4.5]
B (2) [3, 5]
C (3) [0.8, 0.5, 1.2]
*/
如果想要直接遍历出各类商品中的最低价,for in 无法实现,需要再做排序等其它操作。
我们再用 for of 遍历
for (const [key, value] of Object.entries(Price)) {
console.log(key, value);
let min = value[0];
for (const p of value) {
if (min > p) {
min = p;
}
}
console.log(`${key} 类商品的最低价为 ${min} 元`);
}
/* 结果:
A (3) [2.3, 1.5, 4.5]
A 类商品的最低价为 1.5 元
B (2) [3, 5]
B 类商品的最低价为 3 元
C (3) [0.8, 0.5, 1.2]
C 类商品的最低价为 0.5 元
*/