几个循环的区别(forEach、map、filter、reduce、for、for...in、for...of)

220 阅读3分钟

几个循环的区别

  • forEach
  • map
  • filter
  • reduce
  • for
  • for ... in
  • for ... of

forEach

对数组的每一个元素执行一次提供的函数(不能使用 returnbreak 等中断循环),不改变原数组,无返回值 undefined

let arr = ['a', 'b', 'c', 'd']
arr.forEach(function (item, index, arr) {
  console.log(item + ', index = ' + index) // item 是当前元素,index 当前元素索引,arr数组
  console.log(arr)
})

/*
  a, index = 0
  (4) ["a", "b", "c", "d"]
  b, index = 1
  (4) ["a", "b", "c", "d"]
  c, index = 2
  (4) ["a", "b", "c", "d"]
  d, index = 3
  (4) ["a", "b", "c", "d"]
*/

map

map 的作用是 map 中传入一个函数,该函数会遍历该数组,对每一个元素做变换之后返回新数组。

map 不会修改原数组,返回新数组。

  • element:对应数组的每个元素
  • index:数组元素的下标
  • arr:原数组
let arr = [2, 3, 4, 5, 1, 5, 8];
let newArr = arr.map(function (element, index, arr) {
  return element + index;
}); 
console.log(arr); // [2, 3, 4, 5, 1, 5, 8]
console.log(newArr); // [2, 4, 6, 8, 5, 10, 14]

filter

filter 的作用是也是生成一个数组,传入的函数返回值而是布尔类型,返回值为 true 的元素放入新数组,通常来筛选删除不需要的元素。

filter 不会修改原数组,返回新数组。

  • element:对应数组的每个元素
  • index:数组元素的下标
  • arr:原数组
let arr = [2, 3, 4, 5, 1, 5, 8];
let newArr = arr.filter((element, index, arr) => {
  return element % 2 === 0;
});
console.log(arr); // [2, 3, 4, 5, 1, 5, 8]
console.log(newArr); // [2, 4, 8]

reduce

reduce 可以将数组中的元素通过回调函数最终转换为一个值。

  • acc:累计值(第一次的值代表初始化的值)
  • element:当前元素
  • index:当前索引
  • arr:原数组
  • initialValue:可选。传递给函数的初始值

如果第二个参数没有传值,则 acc 为数组的第一个值,elementindex 从第二个值开始;

  • element = arr[1];
  • index = 1;

如果第二个参数传值了,则 acc 为传入的值,elementindex 从第一个值开始;

  • element = arr[0];
  • index = 0;
let arr = [2, 3, 4, 5, 1, 5, 8];
let sum = arr.reduce(function (acc, element, index, arr) {
  return acc + element;
});
console.log(sum); // 28

let sum2 = arr.reduce(function (acc, element, index, arr) {
  return acc + element;
}, 50);
console.log(sum2); // 78

for

  • 自 Javascript 诞生起就一直用的就是 for 循环,它用来遍历数组 ;
  • for 循环中可以使用 returnbreak 等来中断循环 ;
var arr = [1,2,3,4];
for(var i = 0 ; i< arr.length ; i++){
  console.log(arr[i])
}

for ... in

  • 循环遍历的值都是数据结构的键值;
  • for ... in 也可以循环数组但是特别适合遍历对象;
let obj = { a: "1", b: "2", c: "3", d: "4" };
for (let o in obj) {
  console.log(o); // 遍历的实际上是对象的属性名称 a, b, c, d
  console.log(obj[o]); // 这个才是属性对应的值 1,2,3,4
}
var arr = [1, 2, 3, 4];
for (let o in arr) {
  console.log(o); // 0 1 2 3
  console.log(arr[o]); // 1 2 3 4
}

for ... of

它是 ES6 中新增加的语法,用来循环获取一对键值对中的值。

  • 循环一个数组
let arr = ['China', 'America', 'Korea']
for (let o of arr) {
    console.log(o) // China, America, Korea
}
  • 循环一个普通对象(报错)
let obj = { a: "1", b: "2", c: "3", d: "4" };
for (let o of obj) {
  console.log(o); // Uncaught TypeError: obj is not iterable
}

一个数据结构只有部署了 Symbol.iterator 属性,才具有 iterator 接口可以使用 for ... of 循环;例子中的 obj 对象没有 Symbol.iterator 属性,所以会报错。

  • 哪些数据结构部署了 Symbol.iterator 属性
    • 数组 Array
    • Map
    • Set
    • String
    • arguments 对象
    • Nodelist 对象,就是获取的 dom 列表集合

如果想让对象可以使用 for ... of 循环怎么办?使用 Object.keys() 获取对象的 key 值集合后,再使用 for ... of

let obj = { a: "1", b: "2", c: "3", d: "4" };
for (let o of Object.keys(obj)) {
  console.log(o); // a b c d
}

或者使用内置的 Object.values() 方法获取对象的 value 值集合再使用 for ... of

let obj = { a: "1", b: "2", c: "3", d: "4" };
for (let o of Object.values(obj)) {
 console.log(o); // 1 2 3 4
}
  • 循环一个字符串
let str = "love";
for (let o of str) {
  console.log(o); // l o v e
}
  • 循环一个 Map
let iterable = new Map([
  ["a", 1],
  ["b", 2],
  ["c", 3]
]);

for (let [key, value] of iterable) {
  console.log(value); // 1 2 3
}
  • 循环一个 Set
let iterable = new Set([1, 1, 2, 2, 3, 3]);
for (let value of iterable) {
  console.log(value); // 1 2 3
}