JavaScript 中有多种循环和遍历方式,每种方式的使用场景和性能特点不同,适用于不同的数据结构和场景。下面详细介绍几种常见的循环和遍历方式:
1. for
循环
for
是最基本和常见的循环形式,适用于任何需要基于索引操作的场景。它通常用于遍历数组或者执行固定次数的循环。
语法:
for (initialization; condition; final-expression) {
// 循环体
}
示例:
const arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]); // 输出 1, 2, 3, 4, 5
}
说明:
initialization
:用于初始化循环变量,通常在第一次执行循环前运行。condition
:每次迭代前都会检查,如果为true
,则继续执行循环。final-expression
:每次循环体执行完后执行,用于更新循环变量。
2. for...of
循环
for...of
是 ES6 引入的一个用于遍历 可迭代对象(如数组、字符串、Map
、Set
等)的循环方法。相比 for
循环,它更简洁,不需要使用索引,直接访问元素的值。
语法:
for (const element of iterable) {
// 循环体
}
示例:
const arr = [1, 2, 3, 4, 5];
for (const value of arr) {
console.log(value); // 输出 1, 2, 3, 4, 5
}
说明:
- 适用于:数组、字符串、
Map
、Set
,以及其他具有迭代器的对象。 - 无法访问索引:它直接遍历元素的值,不适用于需要访问索引的场景。
3. for...in
循环
for...in
用于遍历对象的可枚举属性,包括对象和数组。它遍历对象的键名(属性名或者索引),而不是值。
语法:
for (const key in object) {
// 循环体
}
示例:
const obj = { name: 'John', age: 30 };
for (const key in obj) {
console.log(key, obj[key]); // 输出 name John 和 age 30
}
说明:
- 适用于:对象属性遍历,但也可以用于数组遍历(不推荐,效率较低)。
- 数组遍历的缺点:
for...in
会遍历数组的索引,可能包括原型链上的属性,且顺序不保证。
不推荐使用 for...in
遍历数组:
const arr = [1, 2, 3, 4, 5];
for (const index in arr) {
console.log(index, arr[index]); // 输出数组的索引和值
}
虽然可以工作,但 for...in
的效率和行为并不适合遍历数组,因此推荐使用 for...of
或传统的 for
。
4. while
循环
while
循环根据条件判断是否继续执行,它会在每次迭代前检查条件。如果条件为 true
,则继续执行循环;如果为 false
,则终止循环。
语法:
while (condition) {
// 循环体
}
示例:
let i = 0;
while (i < 5) {
console.log(i); // 输出 0, 1, 2, 3, 4
i++;
}
说明:
- 适用于:条件不明确,或者不知道循环次数的情况。
- 需要手动更新循环条件:需要在循环体中手动更新条件变量,否则可能会导致无限循环。
5. do...while
循环
do...while
和 while
类似,但它至少执行一次循环体,然后再检查条件。这意味着即使条件最初为 false
,循环体也会执行一次。
语法:
do {
// 循环体
} while (condition);
示例:
let i = 0;
do {
console.log(i); // 输出 0
i++;
} while (i < 0); // 虽然条件为 false,但仍执行一次
说明:
- 至少执行一次:即使条件为
false
,循环体也会被执行一次。 - 适用于:必须至少执行一次的逻辑。
6. Array.forEach()
方法
forEach()
是数组的原型方法,用于遍历数组的每个元素。它允许对数组的每个元素执行给定的回调函数。
语法:
array.forEach(callback(currentValue, index, array) {
// 回调函数体
});
示例:
const arr = [1, 2, 3, 4, 5];
arr.forEach((value, index) => {
console.log(index, value); // 输出数组的索引和值
});
说明:
- 无法中断循环:
forEach
不能被break
、continue
中断。如果需要提前退出循环,请使用其他循环方法(如for
或for...of
)。 - 适合数组遍历,尤其是在需要直接对数组进行操作的场景下。
7. map()
方法
map()
也是数组的方法,它和 forEach
类似,但它返回一个新数组,新数组的每个元素是原数组经过回调函数处理后的值。
语法:
const newArray = array.map(callback(currentValue, index, array) {
// 回调函数体,返回值将成为新数组中的元素
});
示例:
const arr = [1, 2, 3, 4, 5];
const doubled = arr.map(value => value * 2);
console.log(doubled); // 输出 [2, 4, 6, 8, 10]
说明:
- 适用于:需要对数组的每个元素做某种转换,并返回一个新数组的场景。
8. filter()
方法
filter()
用于遍历数组,并返回满足条件的元素组成的新数组。
语法:
const filteredArray = array.filter(callback(currentValue, index, array) {
// 回调函数体,返回 true 或 false
});
示例:
const arr = [1, 2, 3, 4, 5];
const evens = arr.filter(value => value % 2 === 0);
console.log(evens); // 输出 [2, 4]
说明:
- 适用于:根据某些条件过滤数组元素的场景。
9. reduce()
方法
reduce()
方法用于将数组元素组合为一个单一值。它通常用于累计或合并数组中的值。
语法:
const result = array.reduce((accumulator, currentValue, index, array) => {
// 返回新的 accumulator
}, initialValue);
示例:
const arr = [1, 2, 3, 4, 5];
const sum = arr.reduce((total, value) => total + value, 0);
console.log(sum); // 输出 15
说明:
- 适用于:需要对数组进行累计、合并或压缩为单一值的操作。
小结
方法 | 适用场景 | 说明 |
---|---|---|
for | 数组或固定次数的循环 | 手动控制循环索引 |
for...of | 遍历可迭代对象(数组、字符串等) | 简单高效遍历,不访问索引 |
for...in | 遍历对象的可枚举属性 | 遍历对象属性,不推荐用于数组 |
while | 条件循环 | 手动控制条件变量 |
do...while | 至少执行一次循环的场景 | 至少执行一次 |
forEach | 数组遍历 | 无法中断循环 |
map() | 数组元素转换 | 返回新数组 |
filter() | 数组过滤 | 返回满足条件的新数组 |
reduce() | 数组累加 | 返回单一值 |
根据场景选择合适的循环和遍历方法,可以让代码更加简洁和高效。