一、常用方法解析

  说起数组操作,我们肯定第一反应就是想到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

注意: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 } 

但是!很遗憾IE 11 及更早版本也不支持 find()。

 
作者:_呜啦啦啦火车笛
链接:https://juejin.im/post/5ca96c76f265da24d5070563
来源:掘金

forEach、map、filter、find、sort、some等易错点整理的更多相关文章

  1. 【原】javascript笔记之Array方法forEach&map&filter&some&every&reduce&reduceRight

    做前端有多年了,看过不少技术文章,学了新的技术,但更新迭代快的大前端,庞大的知识库,很多学过就忘记了,特别在项目紧急的条件下,哪怕心中隐隐约约有学过一个方法,但会下意识的使用旧的方法去解决,多年前ES ...

  2. JavaScript易错知识点整理

    前言 本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一 ...

  3. JavaScript 易错知识点整理

    本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一些ES ...

  4. JavaScript易错知识点整理[转]

    前言 本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一 ...

  5. ES5 的 forEach, map, filter, some, every 方法

    1:  forEacharray.forEach(callback,[ thisObject]) // 遍历数组里面的所有数字// item 是值, i 是序号, array 是整个数组 [1, 2 ...

  6. 处理数组的forEach map filter的兼容性

    处理数组的forEach //forEach处理 if(!Array.prototype.forEach) { Array.prototype.forEach = function (callback ...

  7. js数组遍历some,foreach,map,filter,every对比

    1.  [...].some(ck)函数       ----      某个一个为true,则为true 对数组中每个元素执行一次ck函数,知道某个元素返回true,则直接返回true.如果都返回f ...

  8. ES6新增的常用数组方法(forEach,map,filter,every,some)

    ES6新增的常用数组方法 let arr = [1, 2, 3, 2, 1]; 一 forEach => 遍历数组 arr.forEach((v, i) => { console.log( ...

  9. JS中some(),every(),forEach(),map(),filter()区别

    JS在1.6中为Array新增了几个方法map(),filter(),some(),every(),forEach(),也就是一共有这么多方法了. 刚开始接触这些倒也记得不是很清楚,在此纪录一下以加深 ...

随机推荐

  1. npm 包下载的各种姿势

    最近在写Node程序的时候,突然对 npm install 的-save和-save-dev 这两个参数的使用比较混乱.其实博主在这之前对这两个参数的理解也是模糊的,各种查资料和实践后对它们之间的异同 ...

  2. SpringMVC常用注解的规则(用法)

    SpringMVC注解 @RequestMapping用法:    a. 用在controller方法上:        标记url到请求方法的映射, 其实就是通过一段url地址, 找到对应需要执行的 ...

  3. mongoDB3.4的sharding集群搭建及JavaAPI的简易使用

    第一部分 在搭建mongoDB之前,我们要考虑几个小问题: 1.我们搭建集群的目的是什么?是多备份提高容错和系统可用性还是横向拓展存储大规模数据还是两者兼有? 如果是为了多备份那么选择replicat ...

  4. tcpdump 命令

    tcpdump命令高级网络 tcpdump命令是一款sniffer工具,它可以打印所有经过网络接口的数据包的头信息,也可以使用-w选项将数据包保存到文件中,方便以后分析. 选项 -a:尝试将网络和广播 ...

  5. Robot Framework 自动化测试--部署篇

    一.产品介绍 Robot Framework是一个基于Python的,可扩展的关键字驱动的测试自动化框架.它是为了端 到端的验收测试(End-To-End Acceptance Test)以及验收测试 ...

  6. Cheerleaders UVA - 11806

    题目大意是: 在一个m行n列的矩形网格中放置k个相同的石子,问有多少种方法?每个格子最多放一个石子,所有石子都要用完,并且第一行.最后一行.第一列.最后一列都要有石子. 容斥原理.如果只是n * m放 ...

  7. Eloquent JavaScript #11# The Document Object Model

    索引 Notes js与html DOM 在DOM树中移动 在DOM中寻找元素 改变Document 创建节点 html元素属性 布局 style CSS选择器 动画 Exercises Build ...

  8. [重要] Django 多条件多表查询实例问题

    当时想做一个多条件查询,但是对于要查询的信息,是分布在不同的表里,这就涉及到了多表查询问题. DjangoBook里提到了一些查询的方式,但是不够全面,就去百度搜了下. 当去网上百度搜多表查询,或多条 ...

  9. php 获取今日、昨日、上周、本周、本月、上月、今年的起始时间戳和结束时间戳的方法

    //php获取今日开始时间戳和结束时间戳 $beginToday=mktime(0,0,0,date('m'),date('d'),date('Y')); $endToday=mktime(0,0,0 ...

  10. devexpress 10.0升级为 15