JavaScript 遍历方法完全指南
2024/8/18大约 5 分钟
JavaScript 遍历方法完全指南
前言
在 JavaScript 开发中,遍历是最常见的操作之一。本文将详细介绍各种遍历方法,包括它们的用法、特点和适用场景。
数组遍历方法
1. for 循环
最基础的遍历方法:
const arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]); // 1, 2, 3, 4, 5
}特点:
- 性能最好
- 可以控制循环流程(break、continue)
- 可以获取索引
2. for...of 循环
ES6 引入的遍历语法:
const arr = [1, 2, 3, 4, 5];
for (const item of arr) {
console.log(item); // 1, 2, 3, 4, 5
}
// 获取索引和值
for (const [index, value] of arr.entries()) {
console.log(index, value); // 0 1, 1 2, 2 3, 3 4, 4 5
}特点:
- 语法简洁
- 可以使用 break、continue
- 支持异步操作
- 适用于所有可迭代对象
3. forEach()
数组的内置方法:
const arr = [1, 2, 3, 4, 5];
arr.forEach((item, index, array) => {
console.log(item, index); // 1 0, 2 1, 3 2, 4 3, 5 4
});特点:
- 语法简洁
- 不能使用 break、continue
- 不返回新数组
- 无法中途停止
4. map()
创建新数组,对每个元素进行处理:
const arr = [1, 2, 3, 4, 5];
const doubled = arr.map(item => item * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// 带索引
const withIndex = arr.map((item, index) => `${index}: ${item}`);
console.log(withIndex); // ["0: 1", "1: 2", "2: 3", "3: 4", "4: 5"]特点:
- 返回新数组
- 不改变原数组
- 适合数据转换
5. filter()
过滤数组元素:
const arr = [1, 2, 3, 4, 5];
const even = arr.filter(item => item % 2 === 0);
console.log(even); // [2, 4]
const filtered = arr.filter((item, index) => index > 2);
console.log(filtered); // [4, 5]特点:
- 返回满足条件的新数组
- 不改变原数组
6. reduce()
将数组减少为单个值:
const arr = [1, 2, 3, 4, 5];
// 求和
const sum = arr.reduce((acc, cur) => acc + cur, 0);
console.log(sum); // 15
// 找最大值
const max = arr.reduce((acc, cur) => Math.max(acc, cur));
console.log(max); // 5
// 数组去重
const duplicates = [1, 2, 2, 3, 3, 4, 5];
const unique = duplicates.reduce((acc, cur) => {
if (!acc.includes(cur)) {
acc.push(cur);
}
return acc;
}, []);
console.log(unique); // [1, 2, 3, 4, 5]特点:
- 功能强大,可以实现很多复杂操作
- 返回单个值
- 可以设置初始值
7. find() 和 findIndex()
查找符合条件的元素:
const arr = [1, 2, 3, 4, 5];
// 找到第一个偶数
const firstEven = arr.find(item => item % 2 === 0);
console.log(firstEven); // 2
// 找到第一个偶数的索引
const firstEvenIndex = arr.findIndex(item => item % 2 === 0);
console.log(firstEvenIndex); // 1
// 找不到返回 undefined 或 -1
const notFound = arr.find(item => item > 10);
console.log(notFound); // undefined8. some() 和 every()
检测数组元素:
const arr = [1, 2, 3, 4, 5];
// 检测是否有偶数
const hasEven = arr.some(item => item % 2 === 0);
console.log(hasEven); // true
// 检测是否都是正数
const allPositive = arr.every(item => item > 0);
console.log(allPositive); // true
// 检测是否都是偶数
const allEven = arr.every(item => item % 2 === 0);
console.log(allEven); // false对象遍历方法
1. for...in 循环
遍历对象的可枚举属性:
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
console.log(key, obj[key]); // a 1, b 2, c 3
}
// 只遍历自身属性
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key, obj[key]);
}
}2. Object.keys()
获取对象的键名数组:
const obj = { a: 1, b: 2, c: 3 };
const keys = Object.keys(obj);
console.log(keys); // ["a", "b", "c"]
keys.forEach(key => {
console.log(key, obj[key]); // a 1, b 2, c 3
});3. Object.values()
获取对象的值数组:
const obj = { a: 1, b: 2, c: 3 };
const values = Object.values(obj);
console.log(values); // [1, 2, 3]
values.forEach(value => {
console.log(value); // 1, 2, 3
});4. Object.entries()
获取对象的键值对数组:
const obj = { a: 1, b: 2, c: 3 };
const entries = Object.entries(obj);
console.log(entries); // [["a", 1], ["b", 2], ["c", 3]]
entries.forEach(([key, value]) => {
console.log(key, value); // a 1, b 2, c 3
});
// 也可以用 for...of
for (const [key, value] of Object.entries(obj)) {
console.log(key, value);
}字符串遍历方法
1. for 循环
const str = "hello";
for (let i = 0; i < str.length; i++) {
console.log(str[i]); // h, e, l, l, o
}2. for...of 循环
const str = "hello";
for (const char of str) {
console.log(char); // h, e, l, l, o
}3. 转换为数组后遍历
const str = "hello";
// 使用 split()
str.split('').forEach(char => {
console.log(char); // h, e, l, l, o
});
// 使用 Array.from()
Array.from(str).forEach(char => {
console.log(char); // h, e, l, l, o
});
// 使用扩展运算符
[...str].forEach(char => {
console.log(char); // h, e, l, l, o
});Map 和 Set 遍历
Map 遍历
const map = new Map([
['a', 1],
['b', 2],
['c', 3]
]);
// 遍历键值对
for (const [key, value] of map) {
console.log(key, value); // a 1, b 2, c 3
}
// 遍历键
for (const key of map.keys()) {
console.log(key); // a, b, c
}
// 遍历值
for (const value of map.values()) {
console.log(value); // 1, 2, 3
}
// 使用 forEach
map.forEach((value, key) => {
console.log(key, value); // a 1, b 2, c 3
});Set 遍历
const set = new Set([1, 2, 3, 4, 5]);
// for...of
for (const value of set) {
console.log(value); // 1, 2, 3, 4, 5
}
// forEach
set.forEach(value => {
console.log(value); // 1, 2, 3, 4, 5
});性能对比
从性能角度排序(由快到慢):
- for 循环 - 最快
- for...of - 较快
- forEach - 中等
- map/filter/reduce - 较慢(但功能强大)
// 性能测试示例
const arr = new Array(1000000).fill(0).map((_, i) => i);
console.time('for');
for (let i = 0; i < arr.length; i++) {
arr[i] * 2;
}
console.timeEnd('for');
console.time('for...of');
for (const item of arr) {
item * 2;
}
console.timeEnd('for...of');
console.time('forEach');
arr.forEach(item => item * 2);
console.timeEnd('forEach');选择建议
根据需求选择:
- 需要中途停止:使用
for或for...of - 数据转换:使用
map - 过滤数据:使用
filter - 累积计算:使用
reduce - 查找元素:使用
find或findIndex - 条件检测:使用
some或every - 简单遍历:使用
forEach或for...of
根据数据类型选择:
- 数组:优先考虑数组方法(map、forEach 等)
- 对象:使用
Object.keys/values/entries+ 数组方法 - 字符串:转换为数组或使用
for...of - Map/Set:使用
for...of或内置的forEach
总结
JavaScript 提供了丰富的遍历方法,每种方法都有其特定的使用场景:
- 传统 for 循环:性能最好,控制最灵活
- for...of:现代语法,支持异步,可中断
- forEach:函数式编程,语法简洁
- map/filter/reduce:数据处理利器,链式调用
- find/some/every:条件查找和检测
