for of、for in、forEach 和 map 的区别

引言

在 JavaScript 中,遍历数组和对象是常见的操作,而我们有多种方式来进行这些遍历,比如 for offor inforEachmap。你能搞懂他们之间的区别吗?本文将详细介绍它们的区别和使用场景。

1. for in:遍历对象的属性(包括继承的属性)

for in 循环用于遍历对象的可枚举属性 。这包括对象的自身属性和继承自原型链的属性。

特点:

  • for in 会遍历对象的所有可枚举属性(包括继承的属性)。
  • 它适用于对象,但不适用于数组,因为数组有索引,且数组本身也是对象,索引可能是对象的属性,for in 会不按顺序遍历数组。
  • 可能会遍历到对象继承的属性。

示例:

1
2
3
4
5
6
7
const person = {
name: 'wyx',
age: 27
};
for (let key in person) {
console.log(key, person[key]); // 输出:name wyx、age 27
}

注意事项:

  • 使用 for in 时,建议使用 hasOwnProperty 方法来检查属性是否是对象自身的属性,避免遍历到继承的属性:
1
2
3
4
5
for (let key in person) {
if (person.hasOwnProperty(key)) {
console.log(key, person[key]);
}
}

2. for of:遍历可迭代对象(数组、字符串、Map、Set)

for of 循环是用于遍历任何可迭代对象 (如数组、字符串、Map、Set 等)。它会逐一返回每个元素的值。

特点:

  • 只适用于可迭代对象 (如数组、字符串、Map、Set)。
  • 返回的是元素的值,而不是键(索引或属性名)。
  • for of 不会遍历对象的属性,它仅遍历数组或其他可迭代对象的元素。

示例:

1
2
3
4
5
const arr = [10, 20, 30];

for (let value of arr) {
console.log(value); // 输出:10、20、30
}

3. forEach:数组的迭代方法

forEach 是数组的内置方法,用于遍历数组元素。它接收一个回调函数,遍历数组时会逐个执行该回调函数。

特点:

  • 只适用于数组。
  • 回调函数接受三个参数:当前元素的值、当前元素的索引、原数组本身。
  • 不支持中途跳出(无法使用 breakreturn 来退出循环)。

示例:

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

arr.forEach((value, index, array) => {
console.log(value, index); // 输出:1 0、2 1、3 2
});

注意事项:

  • forEach 不支持 break 和 continue 语句来控制循环的中断或跳过。
  • 如果需要在遍历过程中跳出,可以考虑使用 for of 或其他手段。

4. map:返回新的数组

map 方法用于创建一个新数组,数组的每一项是原数组元素经过指定回调函数处理后的结果。

特点:

  • 只适用于数组。
  • 会返回一个新的数组,不会改变原数组。
  • 回调函数可以接受三个参数:当前元素的值、当前元素的索引、原数组本身。
  • map 方法会遍历整个数组并返回一个新数组,因此通常用于转换数组中的元素。

示例:

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

const doubled = arr.map(value => value * 2);

console.log(doubled); // 输出:[2, 4, 6]

注意:

  • map 会返回一个新的数组,而不是修改原数组。
  • 如果你只想遍历并不需要返回新的数组,使用 forEach 或其他方式可能更合适。

总结

方法 用途 遍历对象 是否修改原数组 是否返回新数组 是否可以跳出循环 适用场景
for in 遍历对象的属性 对象的属性 可以(使用 break) 对象的属性遍历
for of 遍历可迭代对象的值 数组、字符串、Map、Set 等 可以(使用 break) 数组、字符串、Set、Map 等的遍历
forEach 数组遍历 数组的元素 不可以 数组的遍历
map 返回一个新数组 数组的元素 不可以 数组元素的转换

如何选择

  • 如果需要遍历对象的属性 ,使用 for in(需注意继承的属性)或 Object.keys() 配合 for of
  • 如果需要遍历数组或可迭代对象的元素 ,使用 for of。它简洁且能准确处理数组元素。
  • 如果需要在遍历过程中做一些操作而不改变原数组 ,使用 forEach,但请注意它无法中途跳出。
  • 如果你需要通过映射操作生成一个新的数组 ,使用 map,因为它返回一个新的数组。