记录一下ES中数组遍历以及一些遍历函数的应用场景

287 阅读3分钟

ES数组遍历一直是前端开发中的重中之重,日常很少去总结这些东西,今天趁着休息日,好好的翻阅了一下MDN,然后结合一些demo来做一个数组遍历的总结。不对之处,还请留言区告知~。

注意,大多数方法接收回调函数,回调函数的参数基本一致,均是 value/index/array三个

1、for循环遍历,支持breakcontinue

{
  let arr = [1, 2, 3, 4]
  for (let i = 0; i < arr.length; i++) {
    const item = arr[i]
    console.log(item
  }
}

2、forEach 不可使用break or continue,如果想中止循环,可能需要抛出异常

{
  let arr = [1, 2, 3, 4]
  arr.forEach(value => {
    console.log(value)
  })
}

3、map原型方法,该方法可以返回一个由回调函数返回值组成的一个新数组。


{
  let arr = [1, 2, 3]
  let result = arr.map((value, index, arr) => {
    console.log(value, index, arr)
  })
  console.log(result)

  // 网红面试题

  let numbers = ["16", "20", "30"]
  // 你可能期望返回 [1, 2, 3],但是结果却返回[1, NaN, NaN]
  console.log(numbers.map(parseInt))

  // 这是因为 默认parseInt第二个参数是代表进制,但是上面程序在执行的时候一次将 0,1,2作为进制传递进去了 ,
  // 如果想要解决这个问题可以这样做

  function myParseInt(item) {
    return parseInt(item, 10)
  }
  console.log(numbers.map(myParseInt))

}

4、filter原型方法,该方法返回一个由符合过滤条件的元素的集合。

{
  let arr = [1, 3, 5, 8, 9]

  let result = arr.filter(value => value >= 2)
  console.log(result)
}

5、some原型方法,该方法是用于测试数组中是否至少有一项是符合条件的。

{
  let arr = [1, 2, 3, 4]
  console.log(arr.some(value => value === 2))
}

6、every原型方法,该方法是用于测试数组中所有元素均满足某条件的。

{
  let arr = [0, 2, 4, 6, 8]
  console.log(arr.every(value => value % 2 === 0))
}

7、ES6中的for...of

{
  let arr = [1, 2, 3]
  for (const item of arr) {
    console.log(item)
  }
}

8、面试必考之reduce,这个函数可以说是相当强大,这里需要重点介绍

  • Array.prototype.reduce

/**
 * 函数基本说明
 *
 * 该函数接收两个参数:
 *  1、一个回调函数
 *    这个回调函数包含4个参数:
 *    a. prev 上一次回调函数返回的值或者reduce的初始值
 *    b. current 当前遍历项
 *    c. index 当前遍历索引 如果没有提供reduce的第二个参数,那么这个索引将从1开始
 *    d. array 调用reduce的数组
 *  2、初始值
 *
 *
 * 返回值:
 *  返回回调函数累计处理的结果
 *
 *
 */

上面先简单说明一下这个函数的基本用法,以及参数的含义,下面针对一些应用场景做一些示例

  • 求和
const arr = [100, 23, 34, 102, 28, 47, 75];
let res0 = 0;
for (let index = 0; index < arr.length; index++) {
  res0 += arr[index]
}
console.log(res0);
const res1 = arr.reduce((prev, cur) => {
  return prev + cur
}, 0)
console.log(res1);
  • 扁平化数组
const arr2 = [[1, 3], [4, 6], [5, 7]]

const res3 = arr2.reduce(function (prev, curr) {
  return [...prev, ...curr]
}, [])

console.log(res3);
  • 对象数组转换
const arr3 = [
  { id: 1 },
  { id: 10 },
  { id: 100 },
  { id: 1000 },
  { id: 10000 },
]

const res4 = arr3.reduce((prev, curr) => {
  prev[curr.id] = curr
  return prev
}, {})

console.log(res4);
  • 根据属性分类
const student = [
  { name: 'tom', age: 10, city: 'beijing' },
  { name: 'jay', age: 10, city: 'beijing' },
  { name: 'bill', age: 10, city: 'beijing' },
  { name: 'lily', age: 12, city: 'shanghai' },
  { name: 'lucy', age: 10, city: 'shenzhen' },
  { name: 'jack', age: 5, city: 'guangzhou' },
  { name: 'jerry', age: 7, city: 'hangzhou' },
]

function groupBy(data, key) {
  return data.reduce(function (prev, curr) {
    if (!prev[curr[key]]) {
      prev[curr[key]] = [curr]
    } else {
      prev[curr[key]].push(curr)
    }
    return prev
  }, {})
}

console.log(groupBy(student, 'city'))
console.log(groupBy(student, 'age'))
  • 数组去重
const numbers = [1, 1, 12, 1, 4, 23, 5, 32, 5, 6]

console.log(Array.from(new Set(numbers)));

console.log(numbers.reduce((prev, curr) => {
  prev.includes(curr) ? [...prev] : prev.push(curr)
  return prev
}, []));
  • 管道函数,上一个函数的返回值作为下一个函数的参数
const f1 = function (x) {
  return x * 2
}
const f2 = function (x) {
  return (x + 2) * 3 + 3 
}
const pipe = (...funcs) => input => funcs.reduce((prev, fn) => fn(prev), input)
console.log(pipe(f1, f2)(2));

实际上ES还提供了很多关于数组查找遍历的函数,这里就不再做介绍了,有兴趣的可以查看一下官方文档。

最后

迭代方法

Array.prototype.reduce