JavaScript之引用类型(Array类型)
除了Object类型,Array是ECMAScript中最常用的类型了。
与其他语言不同的是,ECMAScript数组的每一项可以保存任何类型的数据。
而且,ECMAScript数组的大小是可以动态调整的,可以随着数据的添加,数组的长度自动增长。
创建数组的方式
1.使用Array构造函数
var colors1 = new Array();
var colors2 = new Array(20);//创建length为20的数组
var colors3 = new Array("ggr",11,"grr");//以参数中的值来构建数组
2.使用数组字面量表示法
var colors = ["red","gren"];
var values = [1,2,];//强烈建议不要这样使用,因为在不同浏览器下,实现方式不同
//在IE中,第三个值为undefined,在其他浏览器中,只会创建包含1和2的数组。
与对象一样,在使用数组字面量表示法的时候,也不会调用Array构造函数(Firefox3及更早版本除外)
数组的length属性
这个属性不是只读的,可以设置这个属性,可以从数组的末尾移除项或向数组中添加新项。
var colors = ["res","rer","gege"];
colors.length = 2;
alert(colors[2]);//undefined
检测数组
1.对于一个网页或者全局作用域中,使用instanceof就能搞定。(假定只有一个全局执行环境)
value instanceof Array
2.如果网页中出现多个框架,实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的Array构造函数,如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。
为了解决这个问题,ECMAScript5新增了Array.isArray(value)的方法,用于最终确定某个值是不是数组,而不管它是在哪个全局执行环境创建的。
支持Array.isArray()的方法浏览器有IE9+,Firefox4+,Safari5+,Opera10.5+和chrome。
3.针对不支持Array.isArray方法的浏览器,使用下面的方法
在任何值上调用Object原生的toString方法,都会返回一个[object NativeConstructorName]格式的字符串。每个类在内部都有一个[[Class]]属性,这个属性中就指定了上述字符串中的构造函数名。
alert(Object.prototype.toString.call(value));//"[object Array]"
function isArray(value) {
return Object.prototype.toString.call(value) == "[object Array]"; //也可以将这个方法应用与检测某个值是不是原生函数或正则表达式,这个方法不能检测非原生构造函数的构造函数名
}
下面总结一下数组的这些方法
根据我自己的情况,比较熟的方法,就列举一下,就不详细说明了。
1.转换方法(toLocaleString(),toString(),valueOf())
- 所有对象都具有toLocaleString(),toString(),valueOf()方法,其中toString()方法会返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串。
- 而调用valueOf方法返回的还是数组。如果没有显示调用toString()方法,还是会在后台调用toString()方法。
- 这三种方法在默认情况下都会以逗号分隔的字符串的形式返回数组项,如果使用join()方法,则可以使用不同的分隔符。数组的join方法只接受一个参数,即用作分隔符的字符串。
- 如果不给join方法传入任何值,或者给它传入undefined,则使用逗号作为分隔符,IE7及更早版本则会错误的使用字符串“undefined”作为分隔符。
2.类似栈的方法:pop和push,栈的添加和删除都在栈顶进行操作,所以是一个后进先出的数据结构。
- push(推入):可以接受任意数量的参数,然后返回修改后的数组的长度。
- pop(弹出):可以从数组末尾移除最后一项,减少数组的长度,返回删除的项。
3.类似队列的方法:shift和push。队列是先进先出,添加是在队尾,移除是在队首。
- shift:移除数组中的第一项,并返回该项,同时使数组长度减1。
- push:是在数组的末尾逐个添加,并返回修改后的数组的长度。
结合使用shift和push可以像队列一样使用数组。
- unshift:在数组前端添加任意个元素,并返回数组的长度。
- pop:在数组末尾删除一项,返回删除的项。
结合使用unshift和pop可以反向模拟队列,在数组的前端添加项,从数组末端移除项。
4.重排序方法:reverse和sort,这两个返回的是排序过后的数组。
- reverse:顾名思义,就是反转数组项的顺序。
- sort:在默认情况下按升序排列数组项,会调用每个数组项的toString()方法,然后比较得到的字符串,以确定如何排序。即使数组中的每一项都是数值,sort方法比较的也是字符串。
所以在进行数值排序的时候会出现一些问题,可以接受一个函数。
function compare(value1,value2){
//这是升序,从小到大排列
if(value1 < value2){
return -1; //将这里改成return 1,就是从大到小排列
}else if(value1 > value2){
return 1; //将这里改成return -1
}else {
return 0;
}
}
5.操作方法
concat():会基于当前数组中的所有项创建一个新数组,最开始,先创建这个数组的一个副本,然后将接受到的参数添加到这个副本的末尾,最后返回新构建的数组。
如果传递给它的是一个或多个数组,则将这些数组中的每一项添加到结果数组中,如果传递的不是数组,则会简单的添加到结果数组的末尾。
var colors = ["ff","ffff"];
var colo = colors.concat();
console.log(colors); //["ff","fff"]
console.log(colo);//["ff","fff"]
console.log(colors === colo);//false
slice():基于当前数组中的一个或多个项创建一个新数组,接受一个或两个参数,即要返回的起始和结束位置。
- 如果只有一个参数,就返回这个参数指定位置到数组末尾的所有项。
- 如果有两个参数,就是起始位置和结束位置,返回起始位置到结束位置的所有项,但是不包括结束位置的项。
slice也不会改变原数组。
var colors = ["ff","ffff"];
var colo = colors.slice(0,1);
console.log(colors);// ["ff","ffff"]
console.log(colo);//["ff"]
如果参数中有一个是负数,那么就用数组长度加上那个参数确定要返回的位置。
如果第一个参数大于第二个参数,那么就返回空数组。
splice()方法:这个方法是最强大的方法了。主要用途是向数组的中部插入项,返回的都是删除的项组成的数组。
(1)删除:两个参数:删除的起始位置,删除项数。返回删除的项组成的一个数组
(2)插入:可以向指定位置插入任意数量的项。三个参数,起始位置,0(要删除的项数),要插入的项。如果插入多个项,可以传入第四,第五个参数。
(3)替换:可以向指定位置插入任意数量的项,且会删除任意数量的项。三个参数:起始位置,要删除的项数,要插入的任意数量的项。要插入的项和删除的项数不一定相等。
//删除
var color = ["red","green","blue"];
var removed = color.splice(0,1);
console.log(color); //["green","blue"]
console.log(removed);//["red"]
//插入
removed = color.splice(1,0,"yellow","orange");
console.log(removed);//[]
console.log(color);//["green", "yellow", "orange", "blue"]
//替换
removed = color.splice(1,1,"red","purple");
console.log(removed);//["yellow"]
console.log(color);//["green", "red", "purple", "orange", "blue"]
总的来说,这三个方法的参数含义大概相同,可以找个比较好的方法来记忆。第一个是起始位置(删除或者添加),删除的项数,插入的项数。
这个方法对数组的改变,会直接影响到原数组。splice返回的是删除的项组成的数组,如果没有就返回一个空数组。
6.位置方法:indexOf(),lastIndexOf().
返回的是元素在数组中的位置。这两个方法都接受两个参数,要查找的项,(可选的)要开始查找的起始位置的索引。
indexOf是从数组开头进行查找,lastIndexOf是从数组末尾开始向前进行查找。最后返回项在数组中的索引。如果没有找到,就返回-1.
**注意:在比较第一个参数与数组中的每一项时,会使用全等操作符,查找的项必须严格相等“===”
支持这两个方法的常用浏览器有:IE9+,Firefox2+,chrome。
var person = {name:"tom"};
var people = [{name:"tom"}];
var morePeople = [person];
console.log(people.indexOf(person)); //-1,这里输出-1是因为在比较的时候,是使用全等操作符,这里的people中的对象和person这个对象不是同一个对象。
console.log(morePeople.indexOf(person));//0
7.迭代方法(every,filter,forEach,map,some)
一共有5个迭代的方法,每个方法都接收两个参数:要在每一项上运行的函数和(可选的)运行该函数的作用域对象——影响this的值。
传入这些方法中的函数会接受3个参数:数组项的值,该项在数组中的位置和数组对象本身。
every():对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true,否则返回false
filter():对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组
forEach():对数组中的每一项运行给定函数,这个方法没有返回值,即使强制加上return语句返回也不会返回
map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组
some():对数组中的每一项运行给定函数,如果该函数对数组中的任一项返回true,则返回true,否则返回false
支持这些迭代方法的常用浏览器有IE9+,Firefox2+,chrome,Safari3+,Opera9.5+。
8.归并方法reduce(),reduceRight().
这两个方法的区别在于reduce从数组前面进行迭代,一直到最后。reduceRight()是从数组后面进行迭代,到数组的开头。
这两个方法都接受两个参数,一个在每一项上调用的函数和可选的(作为归并基础的初始值)
下面通过这个例子来说明
var values = [1,5,4,7];
var sum = values.reduce(function(prev,cur,index,array){ //这个函数的四个参数:前一个值,当前值,项的索引和数组对象
return prev+cur; //返回的任何值作为第一个参数自动传给下一项,第一次迭代发生在数组的第二项,因此第一个参数是数组的第一项,第二个参数是数组的第二项
});
console.log(sum);//17
支持这两个归并方法的常用浏览器有:IE9+,Firefox3+,chrome,Safari4+,Opera10.5。