forEach、map、filter、find、sort、some等易错点整顿

  近来手头上做了一个很大的背景治理项目,前端对庞杂数据的处置惩罚请求颇高,也确切让自身发现了许多之前被忽视的细节。在此特整顿出来,愿望不熟悉的朋友们们今后能够绕开我踩的这些坑。本文初志在于协助人人梳理一些数组操纵上的重点和易错点,愿望也能协助和提示人人,我会尽可能写的诙谐些,加深人人的影象。程度有限,至心无穷。愿望人人喜好,请不要悭吝你们的赞,感谢

一、经常运用要领剖析

  提及数组操纵,我们肯定第一回响反映就是想到forEach()、map()、filter()等要领,下面离别论述一下各要领的好坏。

1、forEach

1.1 基本点

  forEach的运用频次很高,多用于对数组自身的转变和各元素相干统计性的盘算,主要特征以下:

  1. 能够转变数组自身,没有返回值;
  2. 半途不能用通例操纵跳出轮回,能够用抛出非常(try/catch)的体式格局,但不引荐如许做;

1.2 易错点

  1. forEach()不肯定转变自身数组。我们能够看看数组中的元素是值范例和援用范例场景下,是不是都能取得转变:
var arr1 = [
   {name:'鸣人',age:16},
   {name:'佐助',age:17}
];
var arr2 = [1,2,3];

arr1.forEach(item => { 
  item.age = item.age + 1}
);

//=> [{name:'鸣人',age:17},{name:'佐助',age:18}]

arr2.forEach(item => {
  item = item * 2}
)

// => [1,2,3]

末了的效果是,arr1发生了转变,鸣人、佐助都长了一岁,arr2没有任何转变。所以,能够粗犷得出结论:当数组中元素是值范例,forEach相对不会转变数组;当是援用范例,则能够转变数组

  1. 不支撑链式操纵,所以以下代码是毛病的:
[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) 
})
  1. 不会在迭代之前建立数组的副本,这个运用场景太少太少了,疏忽了…

2、map

  map()功用很壮大,forEach()的一些局限性它许多都能处理。”map”即”映照”,也就是原数组被”映照”成对应新数组。

2.1 基本点

  1. 新建一个数组,须要有承载对象,也意味着原始数组在挪用它后不会发生变化;
  2. 该数组中的每一个元素都挪用一个供应的函数后返回效果。

2.2 易错点

  1. 建立新数组不代表不能用它转变原有数组,你用原有数组去承载就可以够:
let arr = [1,2,3];
arr = arr.map(item => { return item * 2 })

arr一样也会转变,所以这也不省事嘛。。。

  1. map()中每一个元素都要实行响应的回调函数,所以必需要有return(千万别学某些人,推断历程一庞杂,忘了return,末了获得的是个空数组,哭天喊地的~~~),假如你想给数组做肯定的过滤处置惩罚,那map()基本上行不通:
let newArr = [1,2,3,4,5].map(item => { if(item > 3) return item })
// => [undefined, undefined, undefined, 4, 5]

终究获得的效果是[undefined, undefined, undefined, 4, 5]。别和我说你简朴处置惩罚一下就可以拼集用,人生不能拼集,代码也是

3、filter

  map()没法做到的过滤,就交给filter()去完成,这个人人肯定也都晓得。filter()和map()很像,就像周董《东风破》和《发如雪》一样像,也是建立一个新数组,新数组中的元素是挑选出来的相符前提的一切对象。简朴写个例子:

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

这个置信也没啥易错点,有的话迎接批评指出~~~

4、sort()

sort()用于对数组的元素举行排序。排序递次能够是字母或数字,并按升序或降序。

4.1 基本点

1.默许排序按字母升序(更正确一些是依据字符串Unicode码点):

[3,4,2,1,5].sort()
// => [1,2,3,4,5]

['Javascript','Vue','React','Node','Webpack'].sort();
// => ["Javascript", "Node", "React", "Vue", "Webpack"]

4.2 易错点

  1. sort()与map()、filter()等差别,它直接转变原始数组(很主要!);
  2. 假如想根据其他规范举行排序,就需供应比较函数compareFunction(a,b),数组会根据挪用该函数的返回值排序,即a和b是两个将要比较的元素:
  • 假如compareFunction(a,b)小于0,则a排列到b之前;
  • 假如 compareFunction(a, b)即是0,a和b的相对位置稳定(并不保证);
  • 假如 compareFunction(a, b)大于0,b排列到a之前;

直接上例子:

let Users = [
  {name:'鸣人',age:16},
  {name:'卡卡西',age:28},
  {name:'自来也',age:50},
  {name:'佐助',age:17}
];
Users.sort((a,b)=> {
   return a.age - b.age
})

// => 鸣人、佐助、卡卡西、自来也

5、some()

some()也是很好的一个要领,用于搜检数组中是不是有某些相符前提。

5.1 基本点

  1. 只需有一个满足即返回true,以后的不再实行(所以说对机能很友爱!)。
var result = [
   {name:'鸣人',age:16},
   {name:'佐助',age:17}
].some(item => {
    return item.age > 16 
});
=> true

5.2 易错点

  some()和下面讲的every()返回的都是Boolean值,仅此而此,别多想……

6、every()

  假如说some()是”||”推断,那every()就是”&&”推断,它用于检测数组中的每一项是不是都满足前提,只要都满足了才会返回true。这点也很好明白:

var result = [
   {name:'鸣人',age:16},
   {name:'佐助',age:17}
].every(item => {
    return item.age > 16 
});
=> false

二、其他典范要领

  在我们的一样平常工作中,会有许多营业需求是上述要领做不到的,比以下面三个需求:

  1. 给一个数组做去重处置惩罚;
  2. 剖断当前数组里是不是有某个元素,并返回该元素;
  3. 剖断当前数组里是不是有某个元素,并把它去除;

针对需求1,我置信看到”去重”,你肯定会想到new Set(),这也是个经常涌现的口试题;针对需求2,当你看到剖断当前数组中是不是有某个元素,或许会说filter() 不就是干这脏活累活的吗? 还真不是,不信,我们离别睁开讨论一下吧。

1. 数组去重(没你想的那末简朴)

1.1 new Set() 的局限性

  数组去重,基本上论坛上列位大神的口试题里都邑有这个,没错,恰是new Set(),很典范的方法,口试必备:

let tempArr = new Set([1,2,3,3,4,4,5])
// => {1,2,3,4,5} 

//而且已有元素是增加不进去的:
tempArr.add(3) 
// => {1,2,3,4,5}

tempArr.add(6)
// => {1,2,3,4,5,6}

恩,很棒,肯定注重new Set()会将效果转换成对象!但现实工作中我们很少会和元素是值范例的数组打交道,那看看元素是援用范例还行不可:

let mySet = new Set();
mySet.add(1); // Set(1) {1}
mySet.add(5); // Set(2) {1, 5}
mySet.add(5); // Set(2) {1, 5} 这里表现了值的唯一性
mySet.add('some text'); 
[...mySet]
// => [1,5,'some text']

mySet.add({name:'jay Chou',age:40});
mySet.add({name:'jay Chou',age:40});

[...mySet]
// => [1,5,'some text',{name:'jay Chou',age:40},{name:'jay Chou',age:40}]

看到了吧,Set()没法去重元素是援用对象的数组。那接下来咋整呀?

1.2 _.uniqWith()

别忧郁,Lodash帮我们,Lodash是一个一致性、模块化、高机能的JavaScript实用工具库。它有供应给了我们一个很好的要领——_.uniqWith():

import _ from 'lodash';
<script>
var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
_.uniqWith(objects, _.isEqual);
</script>

//=> [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]

个中, _.isEqual(value,other)用于实行深比较来肯定二者的值是不是相称。 _.uniqWith()做去重处置惩罚。

2. 猎取数组中的指定元素

  在工作中我们另有一个比较罕见的场景,就是在数组中找到我想要的那一个,而且返回给我。好的,some()已办不到了,它只会告诉我是不是存在,filter()确切能够做到,然则假如我自身就晓得这个数组里纵然有我想的谁人,也肯定只要一个,不可能涌现多个,所以,出于机能的斟酌,我不想用filter()给我重新遍历到尾,如许怎样办?

2.1 findIndex()

  好了,既然filter()不支撑中缀遍历,那我们就要找一个能中缀遍历的要领,我们能够运用for...of,该要领支撑中缀遍历,然则该要领代码量较大,不发起运用,感兴趣的同砚能够查阅一下。针对这个场景,我们能够运用 findIndex()帮我们先猎取到所需元素的索引值,拿到索引后,你要杀要剐随你便

let testArr = [{name:'鸣人',age:16},{name:'佐助',age:17},{name:'卡卡西',age:26}]
let index = testArr.findIndex(item => { return item.age > 16 });
// => 1

或许也能够运用Lodash供应的_.findIndex(),经由过程对象属性值直接猎取对应索引:

let testArr = [{name:'鸣人',age:16},{name:'佐助',age:17},{name:'卡卡西',age:26}]
let index = _.findIndex(testArr, {name:'佐助'});
// => 1

<font color=red>注重:</font>IE 11 及更早版本不支撑findIndex() 要领。所以,假如对浏览器兼容有请求,那就用Lodash的 _.findIndex()

2.2 find()

  find()望文生义,就是用来在数组中找到我们所须要的元素,而且和some()一样,只需有一个满足即返回该元素,不会过剩遍历,对机能很和睦。

let testArr = [{name:'鸣人',age:16},{name:'佐助',age:17},{name:'卡卡西',age:27},{name:'佐助',age:17}]
let result = testArr.find(item => { return item.name == '佐助'});
// => { name:'佐助',age:17 }

<font color=red>然则!很遗憾IE 11 及更早版本也不支撑 find()</font>。

  在现实工作中,对数组的种种操纵必需要做到纯熟、纯熟、再纯熟,愿望我整顿的这些题目都能对人人有所收成。好了,就这么多吧,背面碰到其他题目了再接着补充,愿望人人喜好!感谢你们的赞!

    原文作者:呜啦啦啦火车笛
    原文地址: https://segmentfault.com/a/1190000018799983
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞