简述forEach、map、filter、every、some、find、findIndex


forEach()

用于遍历数组,无返回值

1.基础点
forEach的使用频率很高,多用于对数组自身的改变和各元素相关统计性的计算,重要特性如下:

  • 可以改变数组自身没有返回值
  • 中途不能用常规操作跳出循环,可以用抛出异常(try/catch)的方式,但不推荐这样做;

2.易错点

  • forEach()数组中的元素是值类型场景下

forEach()不一定改变自身数组。
示例一

var arr=[1,2,5,7,3];
arr.forEach(item=>item*2);
console.log(arr);  //[1,2,5,7,3]

可以看到并没有改变数组的元素值,那么我们来看下面的
示例二

var arr=[1,2,5,7,3];
arr.forEach((item,index,arr)=>arr[index]=item*2);
console.log(arr);  // [2, 4, 10, 14, 6]

可以看到,forEach()可以传入一个匿名函数作为参数,而该匿名函数又含有三个参数,其依次代表

数组遍历时的当前元素item
数组遍历时的当前元素的索引index
正在遍历的数组array

有了这三个参数,可以方便我们做很多事情,比如说示例当中将每一项数组元素翻倍,这时需要用到第一个参数item。
但是,仅仅只是将item乘以2可不行,我们还得将其赋值给原来的数组,这时我们就得用到后面两个参数index和array。

  • forEach()数组中的元素是引用类型场景下
    示例
var arr=[
  {name:'tom',age:16},
  {name:'lily',age:17}
];
arr.forEach(item => { 
  item.age = item.age + 1}
);    
//arr => [{name:'tom',age:17},{name:'lily',age:18}]

arr中发生了改变,tom、lily都长了一岁。

  • 不支持链式操作
    以下代码是错误的:
[1,2,3,4,5].forEach(
  item => console.log(item))
  .filter(item => { 
    return item > 2 
  })
  // Uncaught TypeError: Cannot read property 'filter' of undefined

注意:这里我们说仅仅是forEach()这个方法不支持链式调用,在调用forEach之前,前面的数组你怎么玩链式都没问题,最后返回一个正常数组即可:

// 这个没问题
[1,2,3,4,5].filter(item => { 
  return item > 2})
  .forEach(item => {
    console.log(item) 
  })

3.总结

  • 当数组中元素是值类型,forEach绝对不会改变数组,但可以采用把改变后的值 item*2 赋值给原来的位置,即 arr[index]
  • 当数组中元素是引用类型,则可以改变数组(因为引用的是同一个地址,其实修改的是引用对象内的元素)
  • forEach没有返回值(即便你给forEach加上return也没用),这也间接说明forEach不支持链式调用

map()

用于遍历数组,返回处理之后的新数组

1.基础点

  • 与forEach()的功能类似,但forEach()的一些局限性它很多都能解决。
  • "map"即"映射",也就是原数组被"映射"成对应新数组,需要有承载对象,这样处理数组后也不会影响到原有数组
  • map()中每个元素都要执行相应的回调函数,然后返回结果,所以必须要有return。

2.易错点
创建新数组不代表不能用它改变原有数组,你用原有数组去承载就可以:

let arr = [1,2,3];
arr = arr.map(item => { return item * 2 })
console.log(arr);   //[2,4,6]

原数组也可以被改变,多用于直接修改原数组的情况,用起来很简单。

数组中的元素是引用类型时,map会将改变的值复制一份出来:

var potatos = [
  { id: '1001', weight: 50 },
  { id: '1002', weight: 80 },
  { id: '1006', weight: 60 }];
  //potatos.forEach(item=>item.weight+=10);   
  potatos=potatos.map(item=>item.weight+=10);
  console.log(potatos);   //[60,90,70]

可以看到有时候并不是我们想要的结果。
用forEach就不会有这个顾虑,//potatos = [{ id: '1001', weight: 60 },{ id: '1002', weight: 90 },{ id: '1006', weight: 70 }],但是forEach是在原数组上做的修改。
可以根据自己的需求来选择使用哪个。


filter()

用于筛选数组中满足条件的元素,返回一个筛选后的新数组

1.基础点
map()没法做到的过滤,就交给filter()去完成

let newArr = [1,2,3,4,5].filter(item =>{
  return item > 3
})
//  => [4,5]

2.这个也没什么易错点


every()

用于判断数组中的每一项元素是否都满足条件,返回一个布尔值

1.基础点

它用于检测数组中的每一项是否都满足条件,只有都满足了才会返回true。

var arr=[2,5,-3,-1,4];
//判断arr中是不是每一项都大于0
var isEvery = arr.every(function(item,index,array){
  return item > 0;
});
console.log(isEvery);   // false 

2.总结

  • every返回值是布尔类型
  • every对每一个元素执行一个callback,直到它找到一个使 callback 返回 false的元素,就返回false,之后的不再执行;
  • 直到遍历完成也没有返回false的话,就返回true。

some()

用于判断数组中的是否存在满足条件的元素,返回一个布尔值。

1.基础点
用于检测数组中是否有符合条件的元素,只要有一个满足即返回true,之后的不再执行(所以说对性能很友好!)。

var arr=[2,5,-3,-1,4];
var isSome = arr.some(function(item,index,array){
  return item < 0;
});
console.log(isSome);   // true    

判断arr中有没有小于0的元素,很显然有小于0的元素,所以返回true。

2.总结

  • some返回值是布尔类型
  • some对每一个元素执行一个callback,直到它找到一个使 callback 返回 true的元素,就返回true,之后的不再执行;
  • 直到遍历完成也没有返回true的话,就返回false。
  • 如果说some()是"||"判断,那every()就是"&&"判断

获取数组中的指定元素

在工作中我们还有一个比较常见的场景,就是在数组中找到我想要的那一个,并且返回给我。
some()已经办不到了,它只会告诉我是否存在,filter()确实可以做到,但是如果我本身就知道这个数组里即使有我想的那个,也肯定只有一个,不可能出现多个,所以,出于性能的考虑,我不想用filter()给我从头遍历到尾,这样怎么办?

1.find()
find()用于查找数组中第一个满足条件的元素,返回找到的第一个符合条件的值。

  • 就是用来在数组中找到我们所需要的元素,并且和some()一样,只要有一个满足即返回该元素,不会多余遍历,对性能很友善。
  • 如果没有找到,返回undefined
var arr=[1,4,2,6,3,7];
var big=arr.find(item=>item>5);
console.log(big);  //6 

找到第一个符合条件的元素,就不再往后找。

2.findIndex()
也是查找数组中目标元素,找到就返回元素的位置,找不到就返回-1。

  • 也是只要有一个满足即返回该元素,后边的不再查找。
var arr=[1,4,2,6,3,7];
var bigIndex=arr.findIndex(item=>item>5);
console.log(bigIndex);  //3  
posted @ 2020-08-24 14:41  ZerlinM  阅读(260)  评论(0编辑  收藏  举报