数组
1,数组概念
在实际开发中数组是我们最常用也是最常见的数据类型,使用[]将每一项包裹起来,每一项之间使用“,”号分割,数组每一项都有自己的下标index。每个数组都有自己包含项的总数length。
打个比方:
一群小猫放在一个名字叫arry的箱子里([]),在班级里有5只(length)小猫(‘小黑’,‘小黄’,‘小白’,‘小橘’,‘小别三’),他们的编号(index)分别是0,1,2,3,4。数组化就是arry=[‘小黑’,‘小黄’,‘小白’,‘小橘’,‘小别三’]。length就是5。
拓展E6中可以使用扩展运算符(...)来获取数组元素和复制数组
let arry = [‘小黑’,‘小黄’,‘小白’,‘小橘’,‘小别三’]
let arry2 = [...arry]
arry == arry2 //true
2,创建数组
1),字面量
最常用的创建数组的方式就是字面量方式如下
let arry = []//创建出一个空数组
let catFamily = [‘小黑’,‘小黄’,‘小白’,‘小橘’,‘小别三’]//创建出一个非空数组
2),构造函数(这个比较复杂后面会讲暂时可以只记住这个称呼)
let arry = new Array()//创建了一个空,长度为0的数组 简化写法 let arry = Array()
let arry2 = new Array(5)//创建了一个长度为5的数组,但是每一项的值都是空
let arry3 = newArray(1,2,3)//创建了一个长度3的数组 [1,2,3]
3),拓展
数组构造器Array有两个拓展方法,Array.of,Array.from
(1)Array.of
Array.of与Array构造器相同点当参数为字符串或者两项以上的时候是生成由参数组成的数组
Array(1,2)//[1,2] == Array.of(1,2)//[1,2]
不同在于当参数只有一个数值的时候
Array(5)//会创建一个长度为5,但是没一项都为空的数组
Array.of(5) //会创建一个只有一项,值为5的数组[5]
(2) Array.from
通俗点说是将一个类似数组的可迭代的对象创建成一个新的数组,举个例子
let obj = {0:'a',1:'b',2:'c',length:3}//注意这个length在这个对象里他就是表示有3项是可迭代
let newarry = Array.from(obj,function (value,index) {
console.log(value,index);
return value
})
就可以得到一个[a,b,c]这样的数组。
在日常工作中经常会用的一个方法。
除了object以外string,set,map等包含迭代器的都可以使用Array.form方法获取到一个Array
(3)数组索引
数组中的每个项都有一个索引,非空数组值可以为空,但是索引一定存在。索引通俗点说就是上面讲的编号,不过这里要注意的是数组的索引是从0开始的不是从1,所以最大索引值始终是比length小1。
let arry = [a,b,c,d,e] a的索引index值就是0,b是1,c是2,d是3,e是4。length是5
可以使用arry[index],数组加[]符号,符号内包含索引值来获取数组某位置的值
比如 arry[0] == a
通过索引值还可以增加或者修改数组
arry[1]=f 那么之前的arry就会变成[a,f,c,d,e]
使用length的特性,始终比最后一项的索引值大1,可以使用arry[arry.length]=’g‘这样就会变成
arry = [a,f,c,d,e,g],arry.length数值上加1。从5变成了6
(4),数组判断
判断方法一
Array.isArray(object)//返回一个布尔值true/false
判断方法二
instanceof
object instanceof Array//返回一个布尔值
判断方法三
objcet.constructor == Array //返回一个布尔值
判断方法四
Object.prototype.toString.call(object).slice(8,-1) =='Array' //返回一个布尔值
Object.prototype.toString.call(object)返回的是数据原型字符串[object Array]、[object object]
判断方法五
Array.prototype.isPrototypeOf(object)//返回一个布尔值
3,数组方法(划重点)
数组方法根据对数组的影响可以分为两大类,1,改变原数组,2不改变原数组
1)改变数组的方法(雁过拔毛,兽走留皮)
(1)fill()方法填充数组,语法为array.fill(value,start,end),
参数意义:
value:必传,填充的值,
start:可选,填充开始的位置,
end:可选,填充结束的位置(默认为array.length)
栗子
let arry=Array(5)
arry.fill(3)
就会得到[3,3,3,3,3]这么个数组
arry.fill(3,1,3)
就会得到[空,3,3,空,空] 语义就是将3填充到索引大于等于1并且小于3的位置。start是包含,end是不包含
arry.fill(3,1,-1)//[空, 3, 3, 3, 空]end为负数的时候意味着是length+负数。
arry.fill(3,-1)//[空 ×4, 3] start为负数的时候意味着从length+负数的位置开始到结束
(2)copyWithin()方法与fill类似,
但是比较绕,他填充的内容是通过复制来实现的,语法为copyWithin(target,start,end),自己复制自己然后填充到自己里再返回出去。
target:复制得内容放置到数组的位置
star:复制内容的起点
end:复制内容的终点(默认为array.length)
let arry = [1,2,3,4,5,6]
arry.copyWithin(0,3,5)//[4,5,3,4,5,6] 语义复制arry索引大于等于3小于5的值填充到arry索引0的位置。填充方法不会超出原数组length,比如copyWithin(3,1,5),这里复制[2,3,4,5]四个值,但是从3位置填充如果全部复制过去就会变成[1,2,3,2,3,4,5],超出了原数组length,所以超出部分不会填充进去。也就是最后在位置6的5会被忽略。从而变成[1,2,3,2,3,4]
(3)push()方法
push方法向数组最后位置添加任意参数,
let arry = [1,2,3,4,5,6]
arry.push(7,8,9)//[1,2,3,4,5,6,7,8,9]
(4)pop()方法
pop方法删除数组最后一项
let arry = [1,2,3,4,5,6]
arry.pop()//[1,2,3,4,5]
(5)shift()方法
shift方法删除数组第一项,与pop用法相同,效果相反,一个在头一个在尾
let arry = [1,2,3,4,5,6]
arry.shift()//[2,3,4,5,6]
(6)unshift()
unshift()方法向数组最前增加任意参数,与push用法相同,效果相反,一个在头一个在尾
let arry = [1,2,3,4,5,6]
arry.unshift(7,8,9)//[7,8,9,1,2,3,4,5,6]
(7)sort()方法
sort方法是数组很常用的排序方法,默认是升序排序。不过是看项目第一个值来判断,比如14会拍在4的前面,所以该方法可以接受一个参数,一个对比函数作为参数。
语法:array.sort(sortfn)
let arry = [1,12,3,14,5,6]
arry.sort()//[1,12,14,3,5,6]
所以可以使用对比函数来实现升序或者降序或者其他的排序方式
let arr = [1,12,3,14,5,6]
arr.sort((a,b)=>{return a-b}) // [1,3,5,6,12,14]
(8)splice()数组方法中最灵活的方法之一,可以完成删除,新增,拼接等一些列操作。
语法arry.splice(index,num,item1....itemx)
index:必须,执行操作的位置
num:可选,执行操作的数量,删除的数量
item们:可选,执行操作的内容,需要添加的内容
splice会返回一个新数组,这个数组由被删除的项组成,该方法会改变原数组。
let arr = [1,2,3,4,5,6]
let item = 3
let item2 = [11,22,33]
arr.splice(0,0,item)//[3,1,2,3,4,5,6]
arr.splice(0,1,item)//[3,2,3,4,5,6]
arr.splice(arr.length,0,...tiem2)//[1,2,3,4,5,6,11,22,33]
2)不改变数组的方法(万花丛中过,你还是那个你)
(1),toString()
toString方法可以把数组转换成字符串
let arr = [1,2,3,4,5]
let str = arr.toString()//“1,2,3,4,5”
(2),valueOf()
valueOf方法返回数据本身
let arr = [1,2,3,4,5]
let arr2 = arr.valueOf()//[1,2,3,4,5]
(3),toLocaleString()
toLocaleString方法与toString都是将数组转成字符串,但是toLacleString方法会调用每一项的
toLocaleString方法然后返回
let arr = [{a:'b'},{c:function(){return 2}},'hehe',2,new Date()]
let arr2 = arr.toLacleString()//'[object Object],[object Object],hehe,2,2023/12/20 16:21:50'
let arr3 = arr.toString()//'[object Object],[object Object],hehe,2,Wed Dec 20 2023 16:23:24 GMT+0800 (中国标准时间)'
(4),join()
join()方法把数组所有元素组合成一个字符串,通过分隔符进行分隔。
let arr= [1,2,3,4,5,6]
let str = join(';')//1;2;3;4;5;6 括号内的参数可以为空,默认是,号分割。
(5)slice()返回一个选定项目的数组
语法array.slice(start,end)
start:必要,选取数组开始位置
end:可选,选取数组结束位置
let arr= [1,2,3,4,5,6]
let arr2 = arr.slice(2,5)//[3,4,5,6]
(6)concat()返回一个拼接后的数组
语法concar(arry1,arry2,arry3,.....arryx)
传的参数为需要拼接的数组,第一个是必须的,其他的都是可选的
let arr = [1,2,3,4,5,6]
let arr2 = [11,22,33,44]
let arr3 = arr.concat(arr2)//[1,2,3,4,5,6,11,22,33,44]
(7)reduce()
reduce方法是对数组中的每个元素执行一下reducer函数,将结果汇总为一个单独值返回。
语法:arr.reduce(callback,[initialValue])
callback:必须,每一项需要执行的函数
previousValue:上一次调用回调的返回值,或者是提供的初始值initialValue
currentValue:当前处理的对象
index:当前处理对象索引
array:调用reduce的数组
initalValue:作为初始值给callback调用,可选
let arr = [1,2,3,4]
let sum = arr.reduce((pro,cur,index,arr)=>{
console.log(pro,cur,index)
return pro + cur
},5)
console.log(sum)//sum
执行步骤如下
5 1 0
6 2 1
8 3 2
11 4 3
解释,5是initalValue,1是数组的第一项也是当前要处理的项,0是1的索引。6是上一次处理后的结果也就是5+1,2是当前要处理的项,1是当前要处理的索引,以此类推。最后得到的sum=15
(8)reduceRight()
和reduce()方法一样,只是执行的顺序不同,reduce是从索引0到length,而reduceRight()是从length到0的顺序执行
(9)indexOf(val)
查找数组中是否包含val值,会返回第一个匹配到的项的索引值。正序查找,找不到会返回-1
(10)lastIndexOf(val)
查找数组中是否包含val值,会返回第一个匹配到的项的索引值,不过它是反序查找,从后往前找不到会返回-1
(11)includes(val)
查找数组中是否包含val值,会返回一个布尔值。
(12)find()返回第一个匹配到的元素,如果没有返回undefined
语法:find((val,index,arr)=>{})
val:当前被查找的元素
index:当前被查找的元素的index
arr:元素所属的数组
(13)findIndex()返回第一个匹配到的元素的索引,如果没有返回-1
语法:findIndex((val,index,arr)=>{})
val:当前被查找的元素
index:当前被查找的元素的index
arr:元素所属的数组
let arr = [1,2,3,4,5,6]
let a = arr.find((val,index,arr)=>{return val = 2})//2
let a = arr.find((val,index,arr)=>{return val = 2})//1
(14)迭代器方法
keys(),values(),entries()三个方法分别返回数组的迭代器,keys返回的是index,values返回的是元素,entries返回的元素和index的值对。
console.log([...arr.keys()],[...arr.values()],[...arr.entries()])//[0, 1, 2, 3, 4, 5] ,[1, 2, 3, 4, 5, 6] , [Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)]这里的array里面包含每个元素的index和值比如第一个就是 [0,1]
(15)迭代方法
迭代方法有forEach(),map(),filter(),every(),some(),forEach()方法会改变数组,他们的参数都是接受一个回调函数,回调函数的参数分别是,item当前要执行操作的元素,index当前要执行操作的元素索引,arr当前数组
forEach()遍历每个元素,并且执行一些操作,将元素传递给回调函数,会改变数组,不会有返回值。是直接作用在原数组上的。
map()方法和forEach方法用法一致,但不改变原数组,会返回一个新的元素经过回调函数加工后的新数组。因为有返回值所以可以链式调用 arr.map(item=>{item+1}).map(item=>item+2}
filter()方法用于过滤数组,然后返回满足条件的元素组成的数组。不会改变原数组 arr.filter(item=>itme>2)
every()会遍历所有元素,当所有元素都符合回调函数中的条件会返回一个布尔值。都符合返回true,否则返回false arr.every(item=>item>10)
some()会遍历所有元素,当有一个元素符合回调函数中的条件的时候就会返回true否则返回false
arr.some(item=>item<5)
(16)ES6新增的两个方法
1,for...in
语法 for(let item in arr){
}
两个参数:item:必选,指定的变量代表数组或者对象的元素或者属性
arr/objcet:必选指定迭代的对象
for...in遍历出来的是数组的索引,如果是对象的话遍历出来的是对象的键值
2,for...of
语法:for(let item of object){
}
for...of遍历出来的是数组的值,或者是对象的属性值
for...in会遍历对象的整个原型链,包括原型链上的属性,性能相对较差,for...of则不会。for...in适合用于对象,for...of可以对数组,字符串,映射Map,set集合等可迭代的数据结构使用。
(17)flat()
语法:arr.flat(num) num代表需要展开的层数
flat()返回一个新数组,返回的数组和执行flat方法的数组一致,可以理解为类似复制,但是不同的是flat会展开数组里的数组,然后填充到新数组里举个例子
let arr = [1,2,[1,2,3],3]
let arr2 = arr.flat()// [1,2,1,2,3,3]
看的出来flat方法把arr数组里的数组[1,2,3]展开并且填充到了arr2里。当然如果一个数组里有多层数组,则可以通过num来指定展开。
3,类数组对象
1),arguments
arguments是存在函数中的一个属性,
function fu(name,age,classer){
console.log(arguments,arguments.constru)
}
fu('div','22','3')
callee()其实是函数本身,所以如果在函数内调用改参数就会一直循环使用下去直到内存溢出。
类数组因为是object或者其他类型,不能使用数组的方法,但是有一个神奇的方式
Array.prototype.concat/slice/filter.call(类数组,选择数组的方法的其他参数)
另一种方式就是Array.from(类数组)
4,数组的常见操作
1,数组扁平化(降维),通俗点说就是把数组完全拆开,然后在组合成一个新的数组,包括拆开数组内的数组
1)递归
let arr = [1, [2, [3, 4, 5]]];
let arr2=[]
function fn(array){
for(let item of array){
if(Array.isArray(item)){
fn(item)
}else{
arr2.push(item)
}
}
}
fn(arr)
console.log(arr2) //[1, 2,3,4,5]
2)reduce()迭代(本质还是递归)
let arr = [1, [2, [3, 4, 5]]];
function fn(arr){
return arr.reduce((pre,cur)=>{
return pre.concat(Array.isArray(cur)?fn(cur):cur)
},[])
}
console.log(fn(arr))/[1,2,3,4,5]
3)flat(),
之前介绍过这个方法可以使数组扁平化,不过实际使用的时候经常不知道具体有多少层,这时候我们可以传Infinity,这样不管有多少层都可以拆开
2,数组去重
1)set实现
const array = [1,1, 2, 3, 4, 1, 4, 10, 1, 3, 2];
console.log(Array.from(new Set(array))); // [1, 2, 3, 4, 10]