您现在的位置是:网站首页 > 数组遍历方法文章详情

数组遍历方法

数组是JavaScript中最常用的数据结构之一,处理数组时经常需要遍历元素。JavaScript提供了多种遍历方法,每种方法都有其适用场景和特点。

for循环

最基本的遍历方式是传统的for循环,通过索引访问数组元素:

const fruits = ['apple', 'banana', 'orange'];
for (let i = 0; i < fruits.length; i++) {
  console.log(fruits[i]);
}

这种方式可以精确控制循环过程,包括中断循环或跳过某些元素:

for (let i = 0; i < fruits.length; i++) {
  if (i === 1) continue; // 跳过第二个元素
  if (fruits[i] === 'orange') break; // 遇到orange时终止循环
  console.log(fruits[i]);
}

for...of循环

ES6引入的for...of语法更简洁,直接获取元素值:

for (const fruit of fruits) {
  console.log(fruit);
}

这种写法避免了索引操作,但不能直接获取当前元素的索引。如需索引可以结合entries()方法:

for (const [index, fruit] of fruits.entries()) {
  console.log(index, fruit);
}

forEach方法

数组的forEach方法接受一个回调函数,为每个元素执行操作:

fruits.forEach(function(fruit, index) {
  console.log(index, fruit);
});

使用箭头函数可以更简洁:

fruits.forEach((fruit, index) => console.log(index, fruit));

注意forEach无法使用break中断循环,也不能使用return返回外层函数。

map方法

map方法将数组映射为新数组,不改变原数组:

const upperFruits = fruits.map(fruit => fruit.toUpperCase());
console.log(upperFruits); // ['APPLE', 'BANANA', 'ORANGE']

回调函数接收三个参数:当前元素、索引和数组本身:

const fruitWithIndex = fruits.map((fruit, index, arr) => {
  return `${index + 1}/${arr.length}: ${fruit}`;
});

filter方法

filter根据条件筛选数组元素:

const longFruits = fruits.filter(fruit => fruit.length > 5);
console.log(longFruits); // ['banana', 'orange']

reduce方法

reduce将数组归约为单个值,常用于计算总和或构建对象:

const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 10

复杂归约示例:

const people = [
  { name: 'Alice', age: 21 },
  { name: 'Bob', age: 25 },
  { name: 'Charlie', age: 21 }
];

const ageGroups = people.reduce((groups, person) => {
  const age = person.age;
  if (!groups[age]) {
    groups[age] = [];
  }
  groups[age].push(person);
  return groups;
}, {});

console.log(ageGroups);
// {
//   '21': [{name: 'Alice', age: 21}, {name: 'Charlie', age: 21}],
//   '25': [{name: 'Bob', age: 25}]
// }

some和every方法

some测试是否有元素满足条件,every测试是否所有元素都满足条件:

const hasApple = fruits.some(fruit => fruit === 'apple');
const allLongNames = fruits.every(fruit => fruit.length > 3);

find和findIndex方法

find返回第一个满足条件的元素,findIndex返回其索引:

const firstLongFruit = fruits.find(fruit => fruit.length > 5);
const firstLongIndex = fruits.findIndex(fruit => fruit.length > 5);

性能考虑

不同遍历方法性能差异明显。基准测试表明,在超大数组(如100万元素)上:

  • for循环最快
  • forEachfor慢约3-5倍
  • map/filter等函数式方法更慢,但代码更简洁
// 性能测试示例
const hugeArray = new Array(1000000).fill(0);

console.time('for');
for (let i = 0; i < hugeArray.length; i++) {}
console.timeEnd('for');

console.time('forEach');
hugeArray.forEach(() => {});
console.timeEnd('forEach');

特殊遍历场景

处理稀疏数组时需注意:

const sparseArray = [1, , 3]; // 注意第二个元素是empty
sparseArray.forEach(x => console.log(x)); // 跳过empty
for (const x of sparseArray) console.log(x); // undefined代替empty

遍历类数组对象可先转换为数组:

function printArgs() {
  Array.from(arguments).forEach(arg => console.log(arg));
}
printArgs(1, 2, 3);

现代JavaScript特性

ES2019增加了flatflatMap方法:

const nested = [1, [2, 3], [4, [5]]];
const flat = nested.flat(2); // [1, 2, 3, 4, 5]

const sentences = ["Hello world", "Good morning"];
const words = sentences.flatMap(s => s.split(' ')); 
// ["Hello", "world", "Good", "morning"]

ES2023新增的findLastfindLastIndex

const numbers = [1, 2, 3, 2, 1];
const lastTwo = numbers.findLast(n => n === 2); // 2
const lastTwoIndex = numbers.findLastIndex(n => n === 2); // 3

迭代器协议

数组实现了迭代器协议,可以手动控制迭代:

const iterator = fruits[Symbol.iterator]();
let result = iterator.next();
while (!result.done) {
  console.log(result.value);
  result = iterator.next();
}

并行处理

现代JavaScript支持并行处理数组:

// 使用Web Worker并行处理
if (window.Worker) {
  const worker = new Worker('worker.js');
  worker.postMessage(hugeArray);
  worker.onmessage = e => console.log(e.data);
}

类型化数组

处理二进制数据时使用类型化数组:

const buffer = new ArrayBuffer(16);
const int32View = new Int32Array(buffer);
int32View.forEach((val, i) => {
  int32View[i] = i * 2;
});

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步