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

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

时间2025-06-20 16:19:34分类IT科技浏览4621
导读:数组进阶 上篇介绍了数组的基本概念和一些简单的数组元素操作函数,实际上,数组提供的函数还有很多。...

数组进阶

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

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);//删除掉第一个元素1 console.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,z1,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))//9 console.log(arr.lastIndexOf(0))//10 console.log(arr.includes(10))//false console.log(arr.includes(9))//false

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

NaN的处理

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

let arr = [NaN,1,2,3,NaN] console.log(arr.includes(NaN))//true console.log(arr.indexOf(NaN))//-1 console.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.length console.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 {})//object console.log(typeof [])//object

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

console.log(Array.isArray({}))//false console.log(Array.isArray([]))//true

some                 、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 //判断是否所有的元素都大于2 console.log(arr.every((itm)=>{ if(itm > 2)return true; }))//false

thisArg

在所有的数组方法中             ,除了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() pop shift unshift splice slice concat indexOf、lastIndexOf includes find               、finxIndex filter forEach map sort reverse split reduce                    、reduceRight array.isArray thisArg arr.some   、arr.every
声明:本站所有文章                    ,如无特殊说明或标注      ,均为本站原创发布              。任何个人或组织         ,在未征得本站同意时                    ,禁止复制            、盗用                    、采集      、发布本站内容到任何网站         、书籍等各类媒体平台                  。如若本站内容侵犯了原著者的合法权益         ,可联系我们进行处理      。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
windows10没有激活码怎么办(没有win10激活码怎么办?9月最新win10永久密钥推荐 附激活工具 亲测) 2345和360杀毒哪个好用(360安全卫士和2345安全卫士各有哪些优点_360和2345哪个好)