阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 数组遍历方法

数组遍历方法

作者:陈川 阅读数:38554人阅读 分类: JavaScript

数组是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无法使用breakreturn中断循环,要提前终止需要抛出异常:

try {
  fruits.forEach(fruit => {
    if (fruit === 'banana') throw new Error('Stop iteration');
    console.log(fruit);
  });
} catch (e) {
  if (e.message !== 'Stop iteration') throw e;
}

map方法

map方法遍历数组并返回一个新数组:

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

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

const fruitWithIndex = fruits.map((fruit, index) => `${index}:${fruit}`);
console.log(fruitWithIndex); // ['0:apple', '1:banana', '2:orange']

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((accumulator, current) => accumulator + current, 0);
console.log(sum); // 10

初始值可以省略,此时使用数组第一个元素作为初始值:

const product = numbers.reduce((acc, curr) => acc * curr);
console.log(product); // 24

some和every方法

some测试是否有元素满足条件:

const hasApple = fruits.some(fruit => fruit === 'apple');
console.log(hasApple); // true

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

const allLong = fruits.every(fruit => fruit.length > 3);
console.log(allLong); // true

find和findIndex方法

find返回第一个满足条件的元素:

const firstLong = fruits.find(fruit => fruit.length > 5);
console.log(firstLong); // 'banana'

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

const firstLongIndex = fruits.findIndex(fruit => fruit.length > 5);
console.log(firstLongIndex); // 1

keys、values和entries方法

这些方法返回迭代器对象:

for (const index of fruits.keys()) {
  console.log(index); // 0, 1, 2
}

for (const value of fruits.values()) {
  console.log(value); // 'apple', 'banana', 'orange'
}

for (const [index, value] of fruits.entries()) {
  console.log(index, value); // 0 'apple', 1 'banana', 2 'orange'
}

性能考虑

不同遍历方法性能有差异。对于大型数组,传统for循环通常最快:

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

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

稀疏数组处理

稀疏数组(含有empty项)的处理方式不同:

const sparse = [1,,3];
sparse.forEach(x => console.log(x)); // 1, 3
for (const x of sparse) console.log(x); // 1, undefined, 3

修改原数组

遍历时修改原数组可能导致意外行为:

const numbers = [1, 2, 3];
numbers.forEach((num, index) => {
  numbers.push(num * 2); // 会导致无限循环
});

类数组对象

处理类数组对象(如arguments、NodeList)时:

function logArgs() {
  Array.prototype.forEach.call(arguments, arg => {
    console.log(arg);
  });
}
logArgs(1, 2, 3);

现代JavaScript中更推荐使用Array.from:

const nodeList = document.querySelectorAll('div');
Array.from(nodeList).forEach(div => {
  console.log(div);
});

异步遍历

处理异步操作时,forEach不会等待Promise:

const urls = ['url1', 'url2'];
urls.forEach(async url => {
  await fetch(url); // 不会按顺序执行
});

可以使用for...of配合await

for (const url of urls) {
  await fetch(url); // 按顺序执行
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌