位置: IT常识 - 正文

31.JavaScript数组进阶,一网打尽数组操作函数slice、filter、map、reduce、some、every、find、splice

编辑:rootadmin
31.JavaScript数组进阶,一网打尽数组操作函数slice、filter、map、reduce、some、every、find、splice

推荐整理分享31.JavaScript数组进阶,一网打尽数组操作函数slice、filter、map、reduce、some、every、find、splice,希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:,内容如对您有帮助,希望把文章链接给更多的朋友!

文章目录数组进阶元素删除(对象方式)splice()删除一个元素删除多个元素截断数组元素替换元素插入返回值负索引slice()concat()forEach()indexOf、lastIndexOf、includesfind、findIndexfiltermapsortreversestr.split()和arr.join()reduce、reduceRightArray.isArray()some、everythisArg总结数组进阶

上篇介绍了数组的基本概念和一些简单的数组元素操作函数,实际上,数组提供的函数还有很多。

push、pop、shift和unshift是操作数组首尾两端的函数,上文已经讲过,本文不再赘述。

元素删除(对象方式)

上篇已经简单介绍过,数组就是一个特殊的对象,因此我们可以尝试使用对象的属性删除方法:delete。

举个例子:

let arr = [1,2,3,4,5];delete arr[2];console.log(arr);

代码执行结果如下:

注意观察图中标黄的位置,虽然元素被删除了,但是数组的长度仍然是5,而且删除掉的位置多了一个空。如果我们访问下标为2的元素,会得到如下的结果:

造成这种现象的原因是,delete obj.key是通过key移除对应值的,也就是说delete arr[2]删除了数组中的2:3键值对,当我们访问下标2时,就是undefined了。

而在数组中,我们常常希望删除元素后,元素的位置会被后继的元素填补,数组的长度变短。

这个时候,我们就需要splice()方法。

splice()

需要提前说明的是,splice()方法的功能相当丰富,并非只能删除元素,以下是语法:

arr.splice(start[,deleteCount,e1,e2,...,eN])

splice方法从start位置开始,删除deleteCount个元素,然后原地插入e1,e2,e3等元素。

删除一个元素

以下实例可以从数组中删除一个元素:

let arr = [1,2,3,4,5]arr.splice(0,1);//删除掉第一个元素1console.log(arr)

以上代码删除数组中第一个位置的1个元素,执行结果如下:

删除多个元素

删除多个元素和删除一个元素用法相同,只需要将第二个参数改为指定数量就可以了,举例如下:

let arr = [1,2,3,4,5];arr.splice(0,3);//删除前三个元素console.log(arr);//[4,5]

代码执行结果如下:

截断数组

如果我们只提供一个参数start,那么就会删除数组start位置后面的所有元素,举个例子:

let arr = [1,2,3,4,5]arr.splice(2);//删除从下标为2以及后面的所有元素console.log(arr);//[1,2]

代码执行结果:

元素替换

如果我们提供了超过两个参数,那么就可以替换数组元素,举个例子:

let arr = [1,2,3,4,5];arr.splice(0,2,'itm1','itm2','itm3');console.log(arr);//['itm1','itm2','itm3',3,4,5]

代码执行结果如下:

以上代码实际上执行了两步操作,首先删除从0开始的2个元素,然后在0位置插入三个新的元素。

元素插入

如果我们把第二个参数(删除数量)改为0,那么就可以只插入元素,不删除元素,举个栗子:

let arr = [1,2,3,4,5]arr.splice(0,0,'x','y','z')console.log(arr);//['x','y','z'1,2,3,4,5]

返回值

splice()函数会返回被删除的元素数组,举个例子:

let arr = [1,2,3,4,5]let res = arr.splice(0,3,'x','y')console.log(arr)//['x','y',4,5]console.log(res)//[1,2,3]

代码执行结果:

负索引

我们可以使用负数指示开始操作元素的位置,举个例子:

let arr = [1,2,3,4,5]arr.splice(-1,1,'x','y','z')console.log(arr)//[1,2,3,4,'x','y','z']

代码执行结果如下:

slice()

slice()方法可以截取指定范围的数组,语法如下:

arr.slice([start],[end])

返回一个新数组,新数组从start开始,到end结束,但是不包括end。

举例:

let arr = [1,2,3,4,5]console.log(arr.slice(2,5))//[3,4,5]console.log(arr.slice(1,3))//[2,3]

代码执行结果:

slice()同样可以使用负数下标:

let arr = [1,2,3,4,5]console.log(arr.slice(-3))//[3,4,5]console.log(arr.slice(-5,-1))//[1,2,3,4]

代码执行结果如下:

如果只为slice()方法提供一个参数,就会和splice()一样截断到数组末尾。

concat()

concat()函数可以将多个数组或者其他类型的值拼接称一个长数组,语法如下:

arr.concat(e1, e2, e3)

以上代码将返回一个新的数组,新数组由arr拼接e1、e2、e3而成。

举例:

let arr = [1,2,3]console.log(arr.concat([4,5],6,7,[8,9]))

代码执行结果如下:

普通的对象,即使它们看起来和对象一样,仍然会被作为一个整体插入到数组中,例如:

let arr = [1,2]let obj = {1:'1',2:2}console.log(arr.concat(obj))

代码执行结果:

但是,如果对象具有Symbol.isConcatSpreadable属性,就会被当作数组处理:

let arr = [1,2]let obj = {0:'x', 1:'y', [Symbol.isConcatSpreadable]:true, length:2 }console.log(arr.concat(obj))

代码执行结果:

forEach()

遍历整个数组,为每个数组元素提供一个操作函数,语法:

let arr = [1,2]arr.forEach((itm,idx,array)=>{ ...})

应用举例:

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

代码执行结果:

let arr = [1,2,3,4,5]arr.forEach((itm,idx,array)=>{ console.log(`arr[${idx}] in [${array}] is ${itm}`)})

代码执行结果:

indexOf、lastIndexOf、includes

类似于字符串,indexOf、lastIndexOf、includes可与查询数组中指定元素的下标:

arr.indexOf(itm,start):从start位置开始搜索itm,如果找到返回下标,否则返回-1;arr.lastIndexOf(itm,start):倒序查找整个数组,直至start处,返回第一个查到的下标(也就是数组最后一个匹配项),找不到返回-1;arr.includes(itm,start):从start位置开始搜索itm,找到返回true,否则返回false;

举例:

let arr = [1,2,3,4,5,6,"7","8","9",0,0,true,false]console.log(arr.indexOf(0))//9console.log(arr.lastIndexOf(0))//10console.log(arr.includes(10))//falseconsole.log(arr.includes(9))//false

这些方法在比较数组元素的时候使用的是===,所以false和0是不一样的。

31.JavaScript数组进阶,一网打尽数组操作函数slice、filter、map、reduce、some、every、find、splice

NaN的处理

NaN是一个特殊的数字,三者在处理NaN有细微差别:

let arr = [NaN,1,2,3,NaN]console.log(arr.includes(NaN))//trueconsole.log(arr.indexOf(NaN))//-1console.log(arr.lastIndexOf(NaN))//-1

产生这种结果的原因和NaN本身的特性有关,即NaN不等于任何数字,包括他自己。

这些内容在前面的章节已经讲过了,遗忘的童鞋记得温故知新呀。

find、findIndex

在编程过程中常常会遇到对象数组,而对象是不能直接使用===比较的,如何从数组中查找到满足条件的对象呢?

这个时候就要使用find和findIndex方法,语法如下:

let result = arr.find(function(itm,idx,array){ //itm数组元素 //idx元素下标 //array数组本身 //传入一个判断函数,如果该函数返回true,就返回当前对象itm})

举个栗子,我们查找name属性等于xiaoming的对象:

let arr =[ {id:1,name:'xiaoming'}, {id:2,name:'xiaohong'}, {id:3,name:'xiaojunn'},]let xiaoming = arr.find(function(itm,idx,array){ if(itm.name == 'xiaoming')return true;})console.log(xiaoming)

代码执行结果:

如果没有符合条件的对象,就会返回undefined。

以上代码还可以简化为:

let xiaoming = arr.find((itm)=> itm.name == 'xiaoming')

执行效果是完全相同的。

arr.findIndex(func)的用途和arr.find(func)几乎相同,唯一不同的地方在于,arr.findIndex返回符合条件对象的下标而不对象本身,找不到返回-1。

filter

find和findIndex只能查找一个满足要求的对象,如果一个数组中存在多个满足要求的对象,就需要使用filter方法,语法如下:

let results = arr.filter(function(itm,idx,array){ //和find的用法相同,不过会返回符合要求的对象数组 //找不到返回空数组})

举个例子:

let arr =[ {id:1,name:'xiaoming'}, {id:2,name:'xiaohong'}, {id:3,name:'xiaojunn'},]let res = arr.filter(function(itm,idx,array){ if(itm.name == 'xiaoming' || itm.name == 'xiaohong')return true;})console.log(res)

代码执行结果:

map

arr.map方法可以对数组的每个对象都调用一个函数,然后返回处理后的数组,这是数组最有用的、最重要的方法之一。

语法:

let arrNew = arr.map(function(itm,idx,array){ //返回新的结果})

举例,返回字符串数组对应的长度数组:

let arr = ['I','am','a','student']let arrNew = arr.map((itm)=>itm.length)//return itm.lengthconsole.log(arrNew)//[1,2,1,7]

代码执行结果:

sort

arr.sort对数组进行原地排序,并返回排序后的数组,但是,由于原数组已经发生了改变,返回值实际上没有什么意义。

所谓原地排序,就是在原数组空间内排序,而不是新建一个数组

let arr = ['a','c','b']arr.sort()console.log(arr)

代码执行结果:

注意,默认情况下sort方法是以字母序进行排序的,也就是适用于字符串排序,如果要排列其他类型的数组,需要自定义比较方法

数字数组

let arr = [1,3,2]arr.sort(function(a,b){ if(a > b)return 1; if(a < b)return -1; return 0;})

代码执行结果:

sort函数内部采用了快速排序算法,也可能是timsort算法,但是这些我们都不需要关心,我们只需要关注比较函数就可以了。

比较函数可以返回任何数值,正数表示>,负数表示<,0表示等于,所以我们可以简化数字比较方法:

let arr = [1,3,2]arr.sort((a,b)=> a - b)

如果想要逆序排列只需要交换一下a和b的位置既可以了:

let arr = [1,3,2]arr.sort((a,b)=> b - a)

字符串排序

别忘了字符串比较要使用str.localeCompare(str1)方法呦

let arr = ['asdfas','success','failures']arr.sort((a,b)=>a.localeCompare(b))

代码执行结果:

reverse

arr.reverse用于逆序数组

let arr = [1,2,3]arr.reverse()console.log(arr)//[3,2,1]

这个没啥好说的。

str.split()和arr.join()

还记得字符串分割函数吗?字符串分割函数可以将字符串分割成一个字符数组:

let str = 'xiaoming,xiaohong,xiaoli'let arr = str.split(',')//['xiaoming','xiaohong','xiali']

冷门知识,split函数有第二个参数,可以限制生成数组的长度

let str = 'xiaoming,xiaohong,xiaoli'let arr = str.split(',',2)//['xiaoming','xiaohong']

arr.join()方法用途和split方法相反,可以将一个数组组合成一个字符串。

举个栗子:

let arr = [1,2,3]let str = arr.join(';')console.log(str)

代码执行结果:

reduce、reduceRight

arr.reduce方法和arr.map方法类似,都是传入一个方法,然后依次对数组元素调用这个方法,不同的地方在于,app.map方法在处理数组元素时,每次元素调用都是独立的,而arr.reduce会把上一个元素的调用结果传到当前元素处理方法中。

语法:

let res = arr.reduce(function(prev,itm,idx,array){ //prev是上一个元素调用返回的结果 //init会在第一个元素执行时充当上一个元素调用结果},[init])

试想一下,如何实现一个数字组成的数组元素和呢?map是没有办法实现的,这个时候就需要使用arr.reduce:

let arr = [1,2,3,4,5]let res = arr.reduce((sum,itm)=>sum+itm,0)console.log(res)//15

代码执行过程如下图:

arr.reduceRight和arr.reduce用途相同,只不过从右往左对元素调用方法。

Array.isArray()

数组是对象的一种特例,使用typeof无法准确的分辨二者的区别:

console.log(typeof {})//objectconsole.log(typeof [])//object

二者都是对象,我们需要使用Array.isArray()方法进一步做判断:

console.log(Array.isArray({}))//falseconsole.log(Array.isArray([]))//truesome、every

arr.some(func)和arr.every(func)方法用于检查数字,执行机制和map类似。

some

对每个数组元素执行传入的方法,如果方法返回true,立即返回true,如果所有的元素都不返回true,就返回false。

every

对数组的每个元素执行传入的方法,如果所有元素都返回true,则返回true,否则返回false。

举个例子:

let arr = [1,2,3,4,5]//判断数组是否存在大于2的元素console.log(arr.some((itm)=>{ if(itm > 2)return true;}))//true//判断是否所有的元素都大于2console.log(arr.every((itm)=>{ if(itm > 2)return true;}))//falsethisArg

在所有的数组方法中,除了sort,都有一个不常用固定参数thisArg,语法如下:

arr.find(func,thisArg)arr.filter(func,thisArg)arr.map(func,thisArg)

如果我们传入了thisArg,那么它就会在func中变为this。

这个参数在常规情况下是没什么用处的,但是如果func是一个成员方法(对象的方法),而且方法中使用了this那么thisArg就会非常有意义。

举个例子:

let obj = { num : 3, func(itm){ console.log(this) return itm > this.num;//查找大于3的数字 }}let arr = [1,2,3,4,5,6,7]let newArr = arr.filter(obj.func,obj)console.log(newArr)

代码执行结果:

这里我们可以看到,func中输出的this就是我们传入的thisArg值。

如果我们使用对象成员方法,同时不指定thisArg的值,就会造成this为undefined,从而导致程序错误。

正经人谁用成员方法这样搞呢?哈哈哈

总结push()popshiftunshiftsplicesliceconcatindexOf、lastIndexOfincludesfind、finxIndexfilterforEachmapsortreversesplitreduce、reduceRightarray.isArraythisArgarr.some、arr.every

本文链接地址:https://www.jiuchutong.com/zhishi/300282.html 转载请保留说明!

上一篇:软件行业的最后十年【ChatGPT】(软件行业的最后阶段是)

下一篇:前端经典面试题 | 吊打面试官系列 之 说说你对TypeScript 和 JavaScript的理解(前端经典面试题及答案)

  • 如何在自己手机上查别人的健康码(如何在自己手机上查看别人的微信聊天记录)

    如何在自己手机上查别人的健康码(如何在自己手机上查看别人的微信聊天记录)

  • 华为nova4手机进水充电口闪屏(华为nova4手机进不了主题设置)

    华为nova4手机进水充电口闪屏(华为nova4手机进不了主题设置)

  • 微信好友申请多久过期(微信好友申请多发会叠加吗)

    微信好友申请多久过期(微信好友申请多发会叠加吗)

  • oppor15智慧识屏是什么(oppor15手机智慧识屏怎么用)

    oppor15智慧识屏是什么(oppor15手机智慧识屏怎么用)

  • 找不到文件或目录(文件提示找不到文件所在位置)

    找不到文件或目录(文件提示找不到文件所在位置)

  • 腾讯会议屏幕上有自己的名字(腾讯会议屏幕上的水印怎么去除)

    腾讯会议屏幕上有自己的名字(腾讯会议屏幕上的水印怎么去除)

  • 小米10是2k屏吗(小米10是2k屏吗知乎)

    小米10是2k屏吗(小米10是2k屏吗知乎)

  • oppoa11x微信视频怎么开美颜(oppo微信视频来了没反应)

    oppoa11x微信视频怎么开美颜(oppo微信视频来了没反应)

  • 电脑屏幕解锁按哪个键(电脑屏幕解锁按什么键)

    电脑屏幕解锁按哪个键(电脑屏幕解锁按什么键)

  • 苹果11视频怎么美颜(苹果11视频怎么开美颜和滤镜功能)

    苹果11视频怎么美颜(苹果11视频怎么开美颜和滤镜功能)

  • iphone11左右滑动不了(苹果11左右滑屏幕)

    iphone11左右滑动不了(苹果11左右滑屏幕)

  • 电话被加入黑名单听到的是什么(电话被加入黑名单打电话会提示什么)

    电话被加入黑名单听到的是什么(电话被加入黑名单打电话会提示什么)

  • 美团没有营业执照怎么入驻(美团没有营业执照能上吗)

    美团没有营业执照怎么入驻(美团没有营业执照能上吗)

  • 苹果xsmax可以用5g网络吗

    苹果xsmax可以用5g网络吗

  • 天猫拒收退货流程(天猫拒收退货流程图)

    天猫拒收退货流程(天猫拒收退货流程图)

  • 手机地理位置怎么打开(手机地理位置怎么打开oppo)

    手机地理位置怎么打开(手机地理位置怎么打开oppo)

  • 苹果xr跟8p机身大小(苹果xr和8p重量差多少)

    苹果xr跟8p机身大小(苹果xr和8p重量差多少)

  • 跺的形近字(跺的形近字并且组词)

    跺的形近字(跺的形近字并且组词)

  • 历史时间轴怎么做(历史时间轴怎么整理)

    历史时间轴怎么做(历史时间轴怎么整理)

  • typec数据线3a5a什么意思(数据线typec3a和5a有什么区别)

    typec数据线3a5a什么意思(数据线typec3a和5a有什么区别)

  • 苹果11手机卡怎么放(苹果11手机卡怎么取出来 没有取卡针)

    苹果11手机卡怎么放(苹果11手机卡怎么取出来 没有取卡针)

  • 荣耀v20后置几个摄像头(华为荣耀v20前置和后置摄像头有什么区别)

    荣耀v20后置几个摄像头(华为荣耀v20前置和后置摄像头有什么区别)

  • 小米的msa是什么软件(小米手机msa和mab)

    小米的msa是什么软件(小米手机msa和mab)

  • 微信群聊名称 谁都可以修改吗(微信群聊名称有创意)

    微信群聊名称 谁都可以修改吗(微信群聊名称有创意)

  • 滴滴代驾期待订单报酬怎么填(滴滴代驾等待时间收费标准)

    滴滴代驾期待订单报酬怎么填(滴滴代驾等待时间收费标准)

  • 手机被偷只补卡可以吗(手机被偷补卡后原来的卡还能用吗)

    手机被偷只补卡可以吗(手机被偷补卡后原来的卡还能用吗)

  • 拼多多好友误删怎样加回来(拼多多好友删了)

    拼多多好友误删怎样加回来(拼多多好友删了)

  • 苏黎世湖岸边的室外游泳池,瑞士 (© Amazing Aerial Agency/Offset by Shutterstock)(苏黎世湖天鹅)

    苏黎世湖岸边的室外游泳池,瑞士 (© Amazing Aerial Agency/Offset by Shutterstock)(苏黎世湖天鹅)

  • 北海道的毛腿渔鸮,日本 (© Martin Bailey/Offset by Shutterstock)(北海道的鱼)

    北海道的毛腿渔鸮,日本 (© Martin Bailey/Offset by Shutterstock)(北海道的鱼)

  • 多缴纳社保怎么处理
  • 社保由税务局统一征收的地区
  • 农产品进项税额抵扣最新政策
  • 股权转让和变更法人一样吗?
  • 运输开票的税点是多少
  • 资产负债表的货币资金根据什么填
  • 定额征收需要建账吗
  • 小规模购买金税盘分录
  • 公允价值变动损益属于什么科目
  • 某超市从电器生产厂购进一批电器
  • 外籍个人工资薪金汇出境
  • 个税手续费返还比例
  • 发票抬头不完整能用吗
  • 交通运输业安全心得体会范文
  • 外贸企业出出口退税会计科目怎么做账?
  • 生产型企业税种有哪些
  • 开专用发票可以不写单位与型号么?
  • 个人捐款单位需要记账吗
  • 房产税计税依据房产原值怎么算
  • 钢结构制作安装方案
  • 物流公司开票税率
  • 出售固定资产未收款账务处理
  • 小规模纳税人代收水电费
  • 子公司搭建
  • 职工福利费要申报吗
  • 代扣税款手续费管理办法
  • 当月有进项税额转出怎么结转未交增值税
  • 1697510816
  • 按产品的品种型号规格规定的计划
  • 取得进账发票没发票
  • 收到项目资本金可以记到实收资本吗
  • thinkphp withjoin
  • 享受企业所得税优惠政策的农产品初加工范围
  • 实缴资金少有什么风险
  • 进程antimalware service
  • vue3打包优化
  • php oauth2 单点登录
  • 原材料暂估入库成本结转处理
  • 计提了年终奖还能冲回吗
  • 增值税普通发票查询
  • 报销借款分录怎么做
  • pycharm pypy
  • SqlServer如何通过SQL语句获取处理器(CPU)、内存(Memory)、磁盘(Disk)以及操作系统相关信息
  • dedecms标签怎么用
  • 账簿启用交接表图片
  • 工厂道路设计规范
  • 商业承兑汇票在网银上怎么查询
  • 开具红字增值税普通发票
  • 安装sqlserver2005警告iis
  • mysql 子查询
  • 住房公积金有什么好处和优势?
  • 企业税预缴在哪里
  • 企业接受捐赠固定资产的运费怎么做账
  • 在建工程什么意思
  • 应收账款管理制度
  • 提取备用金怎么做账务处理
  • 事业单位职工福利费
  • 期间损益科目如何结转
  • 销项税大于进项税后,税金如何算
  • 增值税对企业
  • 企业职工福利费支出包括哪些内容
  • 滴滴普通发票
  • 外汇申报材料
  • 发票怎么看是普票还是专票
  • 套现给现金还是转账好
  • 进项发票已认证未抵扣分录
  • 公司增资需要什么流程呢 最新
  • sql数据库连不上可能的原因
  • winxp怎么设置启动项
  • 无法安装osx
  • win10允许访问
  • xp桌面快捷方式不见了
  • windows10怎么老是蓝屏
  • linux常用命令 cat
  • 校园网升级套餐
  • 通过node-mysql搭建Windows+Node.js+MySQL环境的教程
  • 控制角色一致性的5个方法
  • 红宝书csv
  • css中列表样式
  • 利用Matplotlib对一组数据进行分析
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设