数组是值的有序集合。每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引。js数组是无类型,数组元素可以是任意类型,并且同一个数组中的不同元素也可能有不同的类型。数组元素甚至有也可能是对象或其他数组,这允许创建复杂的数据结构,如对象的数组和数组的数组。
数组的第一个元素的索引为0。js数组可能是稀疏的,每个js数组都有一个length属性。该属性就是数组的个数。通过可以用数字的索引来得到元素的值
数组继承来自Array.prototype的属性,它定义了一套丰富的数组操作方法
1.创建数组
1.1 使用数组直接量是创建数组最简单的方法,在方括号将数组元素用逗号隔开即可
eg:
let empty=[];
let primes=[2,3,5,7,11];//有5个数值的数组
let misc=[1.1,true,'a'];//3个不同类型的元素和结尾的逗号
1.2 数组直接量中的值不一定要是常量,它们可以是任意表达式
let base=1024;
let table=[base,base+1,base+2];
1.3 它可以包含对象直接量或其他数组直接量
let b=[[1,{x:1,y:2}],[2,{x:3,y:4}]]
1.4如果省略数组直接量的某个值,省略的元素将被赋予undefined
let count=[1,,3];//数组有3个元素,中间那个值为undefined
let undes=[,,];//数组有2个元素,都是undefined
1.5调用构造函数Array()是创建数组的另一种方法。可以用三种方式调用构造函数
◆ 调用时没有参数
let a=new Array()
该方法创建一个没有任何元素的空数组,等于数组的直接量[ ]
◆调用有一个数值参数,它指定长度
let a=new Array(10);
该技术创建指定长度的数组。当预先知道所需元素的个数时,这种形式的Array()构造函数可以用预分配一个数组空间。注,数组中没有存储值,甚至数组的索引属性‘0’,‘1’等还未定义
◆显示指定两个或多个数组元素或数组的一个非数值元素
let a=new Array(5,4,3,2,1,'testing');
以这种形式,构造函数的参数将会称为新数组的元素。使用字面量比这样使用Array()构造函数要简单的多
2.数组元素的读和写
使用[] 操作符来访问数组中的一个元素。数组的引用位于方括号的左边。方括号是一个返回非负整数的任意表达式。使用该语法既可以读又可以写数组的一个元素,eg:
let a=['world'];//从一个元素的数组开始
let value=a[0];//读0个元素
a[1]=3.14;//第二个元素的值为3.14
let i=2;
a[i]=3;//数组的第三个元素是2
a[i+1]='hello';//数组的第四个元素是‘hello’
使用length属性来访问数组的个数
a.length
注,可以使用负数和非整数来索引数组。这种情况下数值转为字符串,字符串作为属性名来引用
a[-1.23]=true;//创建一个名为‘-1.23’的属性
使用了是非负数的字符串,它就当做数组的索引,而非对象的属性,当使用的一个浮点数和一个整数相等时情况也一样
a['1000']=0;//这是数组的1001个元素
a[1.000]//和a[1]相等
既然数组是对象,那么它们可以从原型中继承元素。数组元素可以定义元素的getter和setter方法,你应该期望它使用非优化的代码路径
3.稀疏数组
稀疏数组就是包含从0个开始的不连续索引的数组。通常,数组的length属性值代表数组中元素的个数。如果数组是稀疏的,length属性值大于元素的个数。可以用Array()构造函数或简单地指定数组的索引值大于当前的数组长度来创建。
let a=new Array(5);//数组没有元素,数组的长度是5
a=[];//创建一个空数组,length=0
a[1000]=0;//赋值添加一个元素,但是设置length为1001
注,当在数组直接量中省略值时不会创建稀疏数组。省略的元素在数组中是存在的,其值时undefined。可以用in操作符检测两者之间的区别
let a1=[,,,];//数组是[undefined,undefined,undefined]
let a2=new Array(3);//该数组根本没有元素
0 in a1;//true a1在索引为0处有一个元素
0 in a2;//false a2在索引0处没有元素
当使用for/in 循环时,a1和a2之间的区别也很明显
4.数组长度
4.1.每个数组有一个length属性,就是这个属性使其区别于常规的js对象。
4.2.针对稠密数组,length属性值代表数组元素的个数。其值比数组中最大的索引大1,eg
[].length;//0,数组没有元素
['a','b','c'].length;//3 最大的索引为2,length为3
4.3当数组是稀疏数组时,length属性值大于元素个数。换一种说法,在数组中找不到一个元素的索引值大于或等于它的长度。如果为一个数组元素赋值时,它的索引i大于或等于现有数组的长度时,length属性的值为i+1;
4.4第二个特殊的行为就是设置length属性为一个小于当前长度的非负整数n时,当前数组中那些索引值大于或等于n的元素将从中删除
let a=[1,2,3,45,5];//从5个元素的数组开始
a.length=3;//现在为a为[1,2,3]
a.length=0;//删除所有的元素
a.length=5;//长度为5
还可以将数组的length属性值设置为大于其当前的长度。实际上这不会向数组中添加新的元素,它只是在数组尾部创建一个空的区域
在es5中,可以用Object.defineProperty()让数组的length变为只读
a=[1,2,3];
Object.defineProperty(a,'length',{writable:false});
a.length=0;
如果让一个数组元素不呢配置,就不能删除它
5.数组元素的添加和删除
我们已经见过添加数组元素的最简单的方法,为值的索引
a=[];
a[0]='zero';
a[1]='one';
也可以使用push()方法在数组末尾增加一个元素或多个元素
let a=[1,2,4];
a.push('zero');//在末尾添加一个元素
a.push('one','two');//在末尾添加两个元素
也可以使用unshift()方法在数组的首部插入一个元素
let a=[1,2,4];
a.unshift('zero');//在数组的头部添加一个元素
可以像删除对象属性一样使用delete运算符来删除数组元素
let a=[1,2,4];
delete a[1];//索引值为1的位置不再有元素
console.log(1 in a)//false 数组索引为1并未在数组中定义
console.log(a)// [1, 空, 4]
console.log(a[1]);//undefined
还可以用splice()方法,是通用的方法插入,删除或替换数组。它会根据修改的length属性并移动元素到更高或较低的索引处
6.数组遍历
6.1使用for循环时遍历数组元素常见的方法
let keys=Object.keys(o);//获得o对象属性名组成的数组
let values=[];//在数组中存储匹配属性的值
for(let i=0;i<keys.length;i++){
let key=keys[i];
values[i]=o[key];
}
如果数组是稠密的,并且所有的元素都是合法的。如果想排除null,undefined 和不存在的元素,可以用下面的案例
for(var i=0;i<a.length;i++){
if(!a[i]){
continue;
}
}
6.2 可以使用for/in循环处理稀疏数组。循环每次将一个可枚举的属性名(包括数组索引)赋值给循环变量
for(let index in spaceArray){
let value= spaceArray[index];
}
注:for/in循环能够枚举继承属性名,如添加到Array.prototype中的方法。由于这个原因,在数组上不应该使用for/in 循环,除非使用额外的检测方法过滤不想要的属性
for(var i in a){
if(!a.hasOwnProperty(i)){
continue;//跳过继承属性
}else if(String(Math.floor(Math.abs(Number(i)))!==i)
continue;
}
6.3 forEach循环
let a=[1,2,4];
a.forEach(function(x){
console.log(x)
})
7.多维数组
js不支持真正的多维数组,但可以用数组的数组近似,访问数组的数据元素,只要简单的使用两次[]操作符即可
eg:
//创建一个多维数组
let table=new Array(10);
for(let i=0;i<table.length;i++){
table[i]=new Array(10);
}
//初始化数组
for(let row=0;row<table.length;row++){
for(let col=0;col<table[row].length;col++){
table[row][col]=row*col
}
}
//使用多维数组来计算5*7
let product=table[5][7];
8数组方法
8.1 join()
Array.join()方法将数组中所有的元素转换为字符串并连接在一起,返回最后生成的字符串。可以指定一个可选字符串在生成的字符串中来分隔数组的各个元素。如果不指定分隔符,默认使用逗号,eg
let a=[1,2,4];
a.join();//'1,2,4'
a.join(' ');//'1 2 3'
a.join('');//'123'
a.join('-');//1-2-3
Array.join()方法是String.split()方法的逆向操作,后者是将字符串分隔成一个数组
8.2 reverse()
Array.reverse()方法将数组中的元素颠倒顺序,返回逆序的数组。它采用了替换,换句话说,它不是重新排列的元素创建新的数组,而是在原先的数组中重新排列它们。eg
let a=[1,3,4];
a.reverse().join();//4,3,1
8.3 sort()
Array.sort()方法将数组中的元素排序并返回排序后的数组。当不带参数调用sort()时,数组元素以字母表排序(如有必要将临时转化为字符串进行比较)
let a=new Array('banana','cherry','applle');
a.sort();
let s=a.join(',');//'apple,banana,cherry'
注:如果数组包含undefined元素,它们会排到数组的尾部。
为了按照其他方式而非字母表顺序进行数组排序,必须给sort()方法传递一个比较函数。该函数决定了它的两个参数在排好序的数组中的先后顺序。假设第一个参数应该在前,比较函数应该返回一个小于0的值。反之,假设第一个参数应该在后,函数应该返回一个大于0的数值,加入这两个值相等(也就是说,它们的顺序无关紧要),函数返回0
let a=[33,4,1111,222];
a.sort(function(a,b){
return a-b;
})
8.4 concat
Aarry.concat() 方法创建并返回一个新数组,它的元素包括concat()的原始数组的元素和concat()的每个参数。如果这些参数中的任何一个自身是数组,则连接的数组是元素,而不是数组本身。concat()不会递归扁平化数组的数组。concat()也不会修改调用的数组
let a=[1,2,4];
a.concat(4,5);//[1,2,3,4,5]
a.concat([4,5]);//[1,2,3,4,5]
8.5 slice()
Array.slice()方法返回指定数组的一个片段或数组。
它的两个参数分别指定了片段的开始和结束的位置。返回的数组包含第一个参数指定的位置毫无所有的但是不含倒数第二个参数指定的位置之间的所有数组的元素;
如果只有一个参数,返回的数组将包含从开始位置到数组结尾的所有元素。
如果参数是负数,它表示相对于数组中最后一个元素的位置。
eg:
let a = [1, 2, 3, 45, 56, 6];
a.slice(0, 3);//[1,2,3]
a.slice(3);//[45,56,6]
a.slice(1,-1);//[2,3,45,56]
a.slice(-3,-2);//[45]
8.6 splice()
Array.splice()方法是在数组中插入或删除元素的通用方法。splice()会修改原数组
splice()能够从数组中删除元素,插入元素到数组中或者同时完成这两种操作。在插入或删除点之后的数组元素会根据增加或减少它们的索引,因此数组的其他部分仍然保持连续。splice()第一个参数指定了插入和(或)删除的起始位置,第二个参数指定了应该从数组删除的个数。如果省略第二个参数,从起始位置开始到数组结尾的所有元素都将删除。splice()返回一个由删除元素组成的数组
let a=[1,2,4,4,5,6,7,8];
a.splice(4);//a[1,2,4,4]
a.splice(1,2);//a[1,4]
a.splice(1,1);//a [1]
console.log(a);//aW
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);//a的值 [1, 2, [1,2], 3, 3, 4, 5]
网友评论