跳到主要内容

数组遍历与迭代

在 JavaScript 中,数组遍历是处理和操作数据的基本操作之一。本文将介绍七种常用的数组遍历方法,并深入探讨生成器和迭代器的使用,以实现更灵活的遍历控制。

七种数组遍历方法

JavaScript 提供了多种数组遍历方法,每种方法都有其独特的用途和优势。这些方法底层都使用for循环实现,但提供了更简洁和功能强大的接口。

forEach(遍历)

forEach方法用于遍历数组中的每一个元素,并对每个元素执行指定的回调函数。这是一个优化版的传统for循环,简化了遍历过程。

const numbers = [1, 2, 3, 4, 5];
numbers.forEach((number) => {
console.log(number);
});
// 输出:
// 1
// 2
// 3
// 4
// 5

map(映射)

map方法遍历数组并对每个元素应用一个函数,返回一个新数组,包含函数处理后的结果。它不会修改原数组。

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled);
// 输出: [2, 4, 6, 8, 10]

filter(过滤)

filter方法创建一个新数组,包含所有通过指定测试的元素。它根据回调函数返回的布尔值决定是否包含当前元素。

const numbers = [1, 2, 3, 4, 5];
const even = numbers.filter((number) => number % 2 === 0);
console.log(even);
// 输出: [2, 4]

reduce(归纳)

reduce方法对数组中的每个元素执行一个归纳函数,最终汇总为单一的值。它适用于累加、累乘等操作。

const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((accumulator, current) => accumulator + current, 0);
console.log(sum);
// 输出: 15

reduceRight(反向归纳)

reduceRight方法与reduce类似,但它从数组的末尾开始向前遍历。这在某些需要逆序处理的场景中非常有用。

const numbers = [1, 2, 3, 4, 5];
const sumReverse = numbers.reduceRight((accumulator, current) => accumulator + current, 0);
console.log(sumReverse);
// 输出: 15

every(每个)

every方法检查数组中的所有元素是否都满足指定的条件。只有当所有元素都通过测试时,返回true

const numbers = [2, 4, 6, 8];
const allEven = numbers.every((number) => number % 2 === 0);
console.log(allEven);
// 输出: true

some(部分)

some方法检查数组中是否至少有一个元素满足指定的条件。只要有一个元素通过测试,返回true

const numbers = [1, 3, 5, 6];
const hasEven = numbers.some((number) => number % 2 === 0);
console.log(hasEven);
// 输出: true

迭代控制的需求

在某些情况下,我们希望在遍历过程中能够手动控制迭代的流程,例如暂停或停止遍历。这时,传统的遍历方法可能无法满足需求。为此,JavaScript 提供了生成器和迭代器,使得遍历过程更加灵活和可控。

迭代一个数组

生成器函数(function *)能够返回一个生成器对象,使得函数的执行可以分阶段进行,使用者可以控制何时继续执行下一步。这为数组的迭代提供了更大的灵活性。

function* generator() {
yield '姓名,素明诚';
yield '年龄: 26';
yield '爱好: 旅游';
return '喜欢JavaScript';
}

const iterator = generator();
console.log(iterator.next()); // { value: '姓名,素明诚', done: false }
console.log(iterator.next()); // { value: '年龄: 26', done: false }
console.log(iterator.next()); // { value: '爱好: 旅游', done: false }
console.log(iterator.next()); // { value: '喜欢JavaScript', done: true }

函数写法

通过生成器函数,可以对数组进行逐步迭代,允许在每次迭代之间进行其他操作或条件判断。

const userInfo = ['姓名,素明诚', '年龄: 26', '爱好: 旅游'];

function* generator(arr) {
for (let i = 0; i < arr.length; i++) {
yield arr[i];
}
return '喜欢JavaScript';
}

const iterator = generator(userInfo);
console.log(iterator.next()); // { value: '姓名,素明诚', done: false }
console.log(iterator.next()); // { value: '年龄: 26', done: false }
console.log(iterator.next()); // { value: '爱好: 旅游', done: false }
console.log(iterator.next()); // { value: '喜欢JavaScript', done: true }

生成器

生成器通过yield关键字控制迭代过程,使得调用者可以在每次next调用时决定是否继续执行。这种控制方式在处理异步操作或需要中断的遍历时尤为有用。

迭代器

迭代器是生成器函数执行后返回的对象,具有next方法。每次调用next方法都会执行生成器函数中的下一条yield语句,直到函数执行完毕。

实现生成器函数

除了使用function*语法,迭代器还可以手动实现,通过返回一个包含next方法的对象来控制迭代过程。

const userInfo = ['姓名,素明诚', '年龄: 26', '爱好: 旅游'];

function createIterator(arr) {
let nextIndex = 0;
return {
next: function () {
if (nextIndex < arr.length) {
return { value: arr[nextIndex++], done: false };
} else {
return { value: '喜欢JavaScript', done: true };
}
},
};
}

const iterator = createIterator(userInfo);
console.log(iterator.next()); // { value: '姓名,素明诚', done: false }
console.log(iterator.next()); // { value: '年龄: 26', done: false }
console.log(iterator.next()); // { value: '爱好: 旅游', done: false }
console.log(iterator.next()); // { value: '喜欢JavaScript', done: true }