javascript-Array
1.序
1.javascript数组索引是32位,自0开始。
2.数组动态扩张和收缩。
3.数组都有length属性,非离散数组Length表示数组中元素个数。离散数组,length大于最大元素的下标。
4.数组属性继承于Array.prototype。大多数方法是泛型的。可以在数组和类数组对象中工作。
7.1.1Array literals
离散数组,数组中有空元素。元素为Undefined
let count=[1,,3];//index 0-2 index 1为空
let undefs[,,];//length=2 无元素
7.1.2 Spread operator
let a=[1,2,3];
let b=[0,...a,4];//b==[0,1,2,3,4]
Set对象可以迅速清除重复元素
let letters=[..."hello world"];
[...new Set(letters)]//->[ h,e ,l ,o, w, r, d]
7.1.3 Array()构造函数
let a=new Array();//空数组
let a=new Array(10);//length=10
let a=new Array(5,4,3,2,1,"tesiting");//初始化数组含有6个元素,第一个参数不代表数组长度
Array构造函数无法创建只有一个成员的数组,只有一个参数它会认为是数组长度。ES6后使用of方法
Array.of()//空数组
Array.of(10)//[10]
Array.of(1,2,3)//[1,2,3]
7.1.5Array.from()
将可枚举或近似数组对象转化为数组
let truearray=Array.from(arraylike);
7.2数组下标字符串和数字具有相同的意义
let o={}
o[1]="one";
o["1"]//"one
使用负数作为下标会转换为字符串下标。
a[-1.23]=true;//property 名为"-1.23"
a["1000"]=0;//index 1000
a[1.000]=1;//a[1]=1;
Javascript没有下标越界错误提示
let a=[true,false];
a[2];//undefined
a[-1]//undefined
7.3松散数组
Sparse Array可以通过构造函数和赋值下标大于当前长度的数组来创建
let a =new Array(5);//length=5
a=[];//length=0,empty
a[1000]=0;//length=1001
当你忽略了数组中的一个值时就是松散数组
let a1=[,];//no elements length=1
let a2=[undefined];//one undefined element
0 in a1//false
0 in a2//true undefined is at index 0
如果你设置了数组长度小于当前数组实际长度,会删除数组中下标大于长度的元素
a=[1,2,3,4,5];
a.length=3;//a=[1,2,3]
a.length=0;//a=[]
a.length=5;//length=5,a=[]
7.6迭代数组
使用For of循环遍历
let letters=[..."Hello,world"];
let string="";
for(let letter of letters){
string+=letter;
}
string//"Hello,world";
对于松散数组,未定义的下标会返回undefined
需要使用下标的情况,使用entries()方法
let everyother="";
for(let[index,letter] of letters.entries()){
if(index%2===0)everyother+=letter;
}
everyother//"Hlowrd"
forEach方法遍历
let uppercase="";
letters.forEach(letter=>{
uppercase+=letter.toUpperCase();
});
uppercase;//"HELLO WORLD"
forEach()会对每个数组元素调用函数,有三个参数,1.数组元素的值。2.下标。3.数组本身
如果你只关心数组元素的值,你可以只传递第一个参数.
forEach()无法使用break语句中断。
let data=[1,2,3,4,5],sum=0;
data.forEach(value=>{sum+=value;});
data.forEach(function(v,i,a){a[i]=v+1};//每个元素加一
对于稀疏数组,遍历时最好进行检查
for(let i=0;i<a.length;i++){
if(a[i]===undefined)continue;
//loop body
}
map方法
let a=[1,2,3];
a.map(x=>x*x);//1,4,9
map方法会返回一个新数组,不更改原数组。map方法应该有返回值。遇到未定义变量也会返回未定义
所以如果是稀疏数组调用Map方法,返回的也是一个稀疏数组。
filter()方法
会过滤,留下符合判断条件的元素。
let a=[5,4,3,2,1];
a.filter(x=>x<3);//[2,1]
a.filter((x,i)=>i%2===0);//[5,3,1],注意这里x是数组元素,i是下标。取下标为偶数的元素
删除空元素
a=a.filter(x=>x!==undefined&&x!==null);
find()和findIndex()方法
find 返回元素,findIndex返回下标
未找到时find返回undefined,findIndex返回-1
let a=[1,2,3,4,5];
a.findIndex(x=>x===3);//返回2
a.findIndex(x=>x<0);//返回-1
a.find(x=>x%5===0);//5
a.find(x=>x%7===0);//undefined
every()和some()方法
every return ture只在所有元素都符合条件的情况。即任意元素
some return true在数组中有元素满足要求的情况即存在元素
let a=[1,2,3,4,5]
a.every(x=>x<10);//true
a.every(x=>x%2===0)//false
a.some(x=>x%2===0)//true
a.some(isNaN)//false
every和some一旦确定返回值会停止遍历。比如every返回false,some返回true的情况。
reduce()和reduceRight()方法
let a=[1,2,3,4,5];
a.reduce((x,y)=>x+y,0);//15
a.reduce((x,y)=>x*y,1);//120
a.reduce((x,y)=>(x>y)?x:y);//5
reduce() 方法对数组中的每个元素按序执行一个提供的 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。
对空数组调用reduce会抛出TypeError
reduceRight()方法和reduce类似,只不过是从右向左遍历数组。
let a=[2,3,4];
a.reduceRight((acc,val)=>Math.pow(val,acc));//2^(3^4)
flat(),flatMap()
[1,[2,3]].flat()//[1,2,3]
[1,[2,[3]]].flat()//[1,2,[3]]
当flat没有参数时,flat进行一层的平整。如果想进一步平整,可以传入参数。
let a=[1,[2,[3,[4]]];
a.flat(1)//=>[1,2,[3,[4]]
a.flat(2)//=>[1,2,3,[4]]
a.flat(3)//=>[1,2,3,4]
a.flat(4)//=>[1,2,3,4]
flatMap() 方法对数组中的每个元素应用给定的回调函数,然后将结果展开一级,返回一个新数组。它等价于在调用 map() 方法后再调用深度为 1 的 flat() 方法(arr.map(...args).flat()),但比分别调用这两个方法稍微更高效一些。
let phrases=["hello world","the definitive guide"];
let words=phrases.flatMap(phrase=>phrase.split(" "));
words//["hello","world","the","definitive","guide"]
concat()方法。
创建和返回连接一个新数组。不更改原数组。会进行一层的flat
let a=[1,2,3];
a.concat(4,5);//[1,2,3,4,5]
a.concat([4,5],[6,7]);//[1,2,3,4,5,6,7]
a.concat(4,[5,[6,7]]);//[1,2,3,4,[5,[6,7]])
a//[1,2,3] 原数组不改变
7.8.4栈,队列,push(),pop(),shift(),unshift()
push()添加一个元素到队尾,返回数组长度。
pop()从队尾删除一个元素,减少队列长度,返回pop的值
let stack=[];
stack.push(1,2);//stack==[1,2];
stack.pop();//stack==[1];return 2
stack.push(3);//stack==[1,3];
stack.pop();//stack==[1],return 3
stack.push([4,5]);//stack==[1,[4,5]]
stack.pop();//stack==1 return [4,5]
stack.pop();//stack==[];return 1
push()方法不平整数组。但可以利用a.push(...values);进行拷贝
unshift()添加一个元素到数组头,将数组其他元素后移一个单位,返回新数组长度
shift()移除并返回数组第一个元素。将数组前移一个单位。
可以通过push()添加一个元素到队尾,shift()移除并获得队首元素来模拟队列先进先出。
let q=[];
q.push(1,2);//[1,2]
q.shift();//[2]
q.push(3);//[2,3]
q.shift();//[3]
q.shift();//[]
一次用unshift()插入多个元素和一次插入一个效果并不相同
let a=[];
a.unshift(1);//[1]
a.unshift(2);//[2,1]
a=[];
a.unshift(1,2);//[1,2]
7.8.5子数组,slice(),splice(),fill(),copyWithin()
slice(),获得子数组
输入负数表示从长度位置倒数
let a=[1,2,3,4,5];
a.slice(0,3);//[1,2,3]
a.slice(3);//[4,5]
a.slice(1,-1)//[2,3,4]
a.slice(-3,-2)//[3] -3从长度倒数3位,为3,—2表示2,含头不含尾,则结果是[3]
注意slice不更改原数组,操作结果是返回到新数组里的。
splice()方法,会更改原数组。可以插入或者删除数组中的数据。
splice()方法的第一个参数时Pos,删除或插入的起始位置,第2个参数是需要操作的长度。
与slice()不同,slice()第二个参数是结束位置。splice()是长度.
如果splice()只传入了一个参数,表示删除从第一个参数后的整个数组。
let a=[1,2,3,4,5,6,7,8];
a.splice(4)//=>[5,6,7,8] a=[1,2,3,4]
a.splice(1,2);//=>[2,3] a=[1,4]
a.splice(1,1);//=>4 a=[1]
splice()后跟的参数表示向指定位置插入元素
let a=[1,2,3,4,5];
a.splice(2,0,"a","b");//=>a=[1,2,"a","b",3,4,5];
a.splice(2,2,[1,2],3);//[1,2,[1,2],3,3,4,5]; 从index 2开始删除2个元素,并插入[1,2],3 "a","b"被删除了
注意splice插入了数组自身,而不是其中的元素。就是没有平整。
ES2023 added the Array toSpliced() method as a safe way to splice an array without altering the original array.
The difference between the new toSpliced() method and the old splice() method is that the new method creates a new array, keeping the original array unchanged, while the old method altered the original array.
fill()方法。
第一个参数是要填充的元素,第二个参数是起始位置,第三个参数是终止位置可以填负数
let a=new Array(5);
a.fill(0);//[0,0,0,0,0]
a.fill(9,1);//[0,9,9,9,9]
a.fill(8,2,-1)//[0,9,8,8,9] 从index 2填充到倒数第二个位置
copyWithin()方法
第一个参数是目的位置,第二个参数是源位置,就是拷贝数据的来源下标,如果不填就默认为0,第三个参数是结束位置,如果未填默认为数组长度。
会拷贝.
copyWithin(target)
copyWithin(target, start)
copyWithin(target, start, end)
详细见https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin
let a=[1,2,3,4,5];
a.copyWithin(1);//[1,1,2,3,4]
a.copyWithin(2,3,5)//[1,1,3,4,4]
a.copyWithin(0,-2)//[4,4,3,4,4]
7.7.6数组搜索和排序算法
indexOf(),lastIndexOf()
没有找到返回-1,indexOf从前往后寻找,lastIndexOf从后向前寻找
let a=[0,1,2,1,0];
a.indexOf(1)//1
a.lastIndexOf(1)//3
a.indexOf(3)//-1
indexOf() lastIndexOf()使用的是===进行比较的。如果是对象数组,只有对象指向同一内存空间时才相等,这种情况下建议使用高级函数find(),并自定义比较函数。
indexOf(),和lasgIndexOf()的第二个参数表示起始位置,可以填写负值,表示从尾向前几个单位。
例,寻找所有满足条件的下标
function finall(a,x){
let results=[],len=a.length,pos=0;
while(pos<len){
pos=a.indexOf(x,pos);
if(pos===-1)break;
results.push(pos);
pos=pos+1;
}
return results;
}
includes()方法。
单参数,如果数组含有此参数,返回true。否则返回false。
和indexOf()不同,indexOf使用===判断是否相等。NaN和其他值都不等,且NaN不等于NaN
includes()则判断NaN等于NaN
let a=[1,true,NaN];
a.includes(true);//true
a.includes(2);//false
a.includes(NaN);//true
a.indexOf(NaN);//-1
sort()方法
如果sort()没有参数传入,默认按字母表顺序排列。
如果array中有undefined 元素,会被置于数组末尾。
如果要按其他方式排列,需要向sort()传入一个比较函数。如果两个数据,第一个数据在前,第二个数据在后,比较函数应返回一个负值。第一个数据在后,第二个数据在前,比较函数应该返回一个正值。相等,比较函数应该返回0。
let a=[33,4,1111,222];
a.sort();//[1111,222,33,4]
a.sort(function(a,b){
return a-b;
});//[4,33,222,1111]
a.sort((a,b)=>b-a);//[1111,222,33,4] a小b大,b-a为正值,b排列在a前。即降序排列。
例,忽略大小写排列字符串
let a=["ant","Bug","cat","Dog"];
a.sort();//["Bug","Dog","ant","cat"];大小写敏感
a.sort(function(s,t){
let a=s.toLowerCase();
let b=s.toLowerCase();
if(a<b)return -1;
if(a>b)return 1;
return 0;
});//忽略大小写
reverse()函数,逆向数组,会改变数组本身
let a=[1,2,3];
a.reverse();//a===[3,2,1]
7.8.7数组转换为字符串
join()方法。将数组转换为字符串并链接他们,返回值是处理完毕的字符串.参数是分隔符。不填就以,分隔
let a=[1,2,3];
a.join()//"1,2,3"
a.join(" ")//"1 2 3"
a.join("")//"123"
let b=new Array(10);
b.join("-");//"---------" 9个连字符
toString()方法,类似于不传入参数的join方法
[1,2,3].toString()//"1,2,3"
["a","b","c"].toString()//"a,b,c"
[1,[2,"c"]].toString()//"1,2,c"
toLocaleString()方法,对于每个元素,分别调用toLocaleString()方法。
7.8.8静态方法
Array.isArray([])//true,判断一个未知对象是否是数组
let a={"0":"a","1":"b","2":"c",length=3};//类数组对象
Array.prototype.join.call(a,"+")
Array.prototype.map.call(a,x=>x.toUpperCase())
Array/prototype.slice.call(a,0)//["a","b","c"]
7.10字符串作为数组
字符串是不可改变的值,当它被视为数组时,是只读数组。数组方法push(),sort(),reverse(),splice()方法会更改数组,所以自然不能用于字符串。但是不会报错,只是不执行而已。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现