Javascript 零基础教程

JavaScript 数组迭代

数组迭代 (Array Iteration) 是 JavaScript 中的一个基本概念,它允许你处理数组中的每一个元素。

掌握数组迭代技术能让你对数据执行各种操作,例如转换数值、筛选特定元素,或者仅仅是对每一项应用一个函数。

本章节将深入探讨三个强大的数组方法:forEachmapfilter。理解这些方法将显著提升你高效处理数组的能力。

1 forEach: 对每个元素执行函数

forEach 方法是一种遍历数组中每个元素并对每个元素执行一次所提供函数的方法。当你需要对每一项执行操作时,它本质上是传统 for 循环的一种更简洁、更易读的替代方案。

1.1 基本用法

forEach 的基本语法如下:

array.forEach(function(currentValue, index, array) {
  // 你的代码
});
  • currentValue (当前值): 数组中正在处理的当前元素的值。
  • index (索引) (可选): 正在处理的当前元素的索引。
  • array (数组) (可选): 调用 forEach 的数组本身。

让我们看一个例子:

const colors = ['red', 'green', 'blue'];

colors.forEach(function(color) {
  console.log(color);
});

// 输出:
// red
// green
// blue

在这个例子中,forEach 方法遍历 colors 数组,对于每种颜色,它都会将颜色打印到控制台。注意,我们将一个匿名函数(没有名字的函数)作为参数传递给了 forEach

1.2 使用箭头函数

自 ES6 (ECMAScript 2015) 起,我们可以使用箭头函数来实现更简洁的语法:

const numbers = [1, 2, 3];

numbers.forEach(number => console.log(number * 2));

// 输出:
// 2
// 4
// 6

在这里,箭头函数 number => console.log(number * 2) 接收 numbers 数组中的每个 number,并将其两倍的值打印到控制台。

1.3 访问索引和数组

你也可以在 forEach 循环中访问当前元素的索引和原始数组:

const fruits = ['apple', 'banana', 'orange'];

fruits.forEach(function(fruit, index, array) {
  console.log(`索引 ${index} 处的水果是 ${fruit}`);
  console.log(`原始数组是: ${array}`);
});

// 输出:
// 索引 0 处的水果是 apple
// 原始数组是: apple,banana,orange
// 索引 1 处的水果是 banana
// 原始数组是: apple,banana,orange
// ...

这个例子演示了如何在 forEach 回调函数中访问索引和原始数组。虽然它们可用,但 indexarray 参数的使用频率通常低于 currentValue

重要提示:forEach 不会返回新数组

理解这一点至关重要:forEach 不会创建一个新数组。它只是对现有数组的每个元素执行提供的函数。如果你需要转换元素并创建一个包含修改后值的新数组,你应该使用 map 方法,我们接下来会讨论它。

2. map: 转换数组元素

map 方法通过对原始数组中的每个元素应用提供的函数来创建一个数组。当你需要转换数组中的值而不修改原始数组本身时,这非常有用。

2.1 基本用法

map 的基本语法如下:

const newArray = array.map(function(currentValue, index, array) {
  // 返回转换后的值
  return transformedValue;
});
  • currentValue: 数组中正在处理的当前元素的值。
  • index (可选): 当前元素的索引。
  • array (可选): 调用 map 的数组。
  • transformedValue: 将被添加到新数组中的值。这个值必须由函数返回。

让我们看一个使用 map 将数组中的数字翻倍的例子:

const numbers = [1, 2, 3, 4, 5];

const doubledNumbers = numbers.map(function(number) {
  return number * 2;
});

console.log(doubledNumbers); // 输出: [2, 4, 6, 8, 10]
console.log(numbers); // 输出: [1, 2, 3, 4, 5] (原始数组未改变)

如你所见,map 遍历 numbers 数组,将每个数字乘以 2,并返回一个包含转换后值的数组 doubledNumbers。原始的 numbers 数组保持不变。

2.2 使用箭头函数

同样,箭头函数可以简化语法:

const numbers = [1, 2, 3, 4, 5];
const squaredNumbers = numbers.map(number => number * number);

console.log(squaredNumbers); // 输出: [1, 4, 9, 16, 25]

这个例子演示了如何使用简洁的箭头函数创建一个包含原始数组中每个数字平方的新数组。

2.3 转换数组中的对象

map 非常适合转换对象数组。例如,假设你有一个用户对象数组,你想创建一个只包含用户名的新数组:

const users = [
  { id: 1, username: 'john_doe', email: 'john@example.com' },
  { id: 2, username: 'jane_smith', email: 'jane@example.com' },
  { id: 3, username: 'peter_jones', email: 'peter@example.com' }
];

const usernames = users.map(user => user.username);

console.log(usernames); // 输出: ['john_doe', 'jane_smith', 'peter_jones']

在这里,map 方法从每个用户对象中提取 username 属性,并创建一个只包含用户名的显数组。

3. filter: 根据条件筛选元素

filter 方法创建一个数组,其中只包含原始数组中满足提供条件的元素。这对于从数组中提取特定的数据子集非常有用。

3.1 基本用法

filter 的基本语法如下:

const newArray = array.filter(function(currentValue, index, array) {
  // 返回 true 以将元素包含在新数组中,
  // 返回 false 以排除它。
  return condition;
});
  • currentValue: 数组中正在处理的当前元素的值。
  • index (可选): 当前元素的索引。
  • array (可选): 调用 filter 的数组。
  • condition: 一个计算结果为 truefalse 的表达式。

让我们看一个从数组中筛选偶数的例子:

const numbers = [1, 2, 3, 4, 5, 6];

const evenNumbers = numbers.filter(function(number) {
  return number % 2 === 0;
});

console.log(evenNumbers); // 输出: [2, 4, 6]
console.log(numbers); // 输出: [1, 2, 3, 4, 5, 6] (原始数组未改变)

在这个例子中,filter 遍历 numbers 数组。对于每个数字,它检查其是否为偶数 (number % 2 === 0)。如果条件为真,该数字将被包含在新的 evenNumbers 数组中。否则,它将被排除。原始 numbers 数组保持不变。

3.2 使用箭头函数

forEachmap 一样,箭头函数提供了更简洁的语法:

const numbers = [1, 2, 3, 4, 5, 6];
const oddNumbers = numbers.filter(number => number % 2 !== 0);

console.log(oddNumbers); // 输出: [1, 3, 5]

这个例子使用简洁的箭头函数筛选出了 numbers 数组中的奇数。

3.3 筛选对象数组

当处理对象数组时,filter 特别强大。例如,假设你有一个产品对象数组,你想筛选出缺货的产品:

const products = [
  { id: 1, name: 'Laptop', price: 1200, inStock: true },
  { id: 2, name: 'Mouse', price: 25, inStock: true },
  { id: 3, name: 'Keyboard', price: 75, inStock: false },
  { id: 4, name: 'Monitor', price: 300, inStock: true }
];

const inStockProducts = products.filter(product => product.inStock);

console.log(inStockProducts);
// 输出:
// [
//   { id: 1, name: 'Laptop', price: 1200, inStock: true },
//   { id: 2, name: 'Mouse', price: 25, inStock: true },
//   { id: 4, name: 'Monitor', price: 300, inStock: true }
// ]

这个例子筛选 products 数组,只保留那些 inStock 属性为 true 的产品。

3.4 结合使用 mapfilter

你可以将 mapfilter 链式调用,以执行更复杂的转换。例如,假设你想获取所有有库存产品的名称,并将它们转换为大写:

const products = [
  { id: 1, name: 'Laptop', price: 1200, inStock: true },
  { id: 2, name: 'Mouse', price: 25, inStock: true },
  { id: 3, name: 'Keyboard', price: 75, inStock: false },
  { id: 4, name: 'Monitor', price: 300, inStock: true }
];

const inStockProductNames = products
  .filter(product => product.inStock)
  .map(product => product.name.toUpperCase());

console.log(inStockProductNames); // 输出: ['LAPTOP', 'MOUSE', 'MONITOR']

首先,我们使用 filter 获取所有有库存的产品。然后,我们使用 map 提取每个有库存产品的 name 属性并将其转换为大写。

4. 总结

简而言之:

  • forEach 用于对数组中的每个元素执行函数,不创建新数组。
  • map 用于转换数组中的每个元素,并创建包含转换后值的新数组。
  • filter 用于创建一个新数组,其中只包含原始数组中满足特定条件的元素。

掌握这些数组迭代方法对于高效和有效的 JavaScript 编程至关重要。