您的位置:首页 > Web前端 > JavaScript

Javascript数组——必备知识全解

2015-01-19 16:16 99 查看

1.数组的定义

1) 直接使用方括号:

Var arr=['a','b','c'].

2)除了直接使用方括号创建,数组还可以使用JavaScript内置的Array构造函数创建。

var a = new Array();

var a = new Array(1);
a // [undefined × 1]
a.length // 1

var a = new Array(2);
a // [undefined × 2]
a.length // 2

var a = new Array(1,2);
a // [1,2]
a.length // 2
上面代码说明,Array构造函数的用法不符合直觉。没有参数时,返回一个空数组;使用一个参数时,返回一个指定长度的空数组;如果使用非数值(字符串、布尔值、对象等)作为参数,则该值是新数组的成员;使用多个参数,返回一个指定成员的数组。所以,建议总是直接采用方括号创建数组。

2.数组的length属性

只要是数组,就一定有length属性。且数组的length属性是一个动态的值。

Var  arr=[‘a’,’b’];
arr.length=2

arr[2]=’c’;
arr.length;   //3;

arr[9]=’d’;
arr.length;  //10;


length属性是可写的。如果设置一个小于当前成员个数的值,该数组的成员会自动减少到length设置的值。
var arr=[1,2,3];
arr.length ;  //3;

arr.length=2;
arr   //[1,2]

所以,将数组清空的一个有效方法,就是将length属性设为0;
Var arr=[1,2,3];
arr.length=0;
如果人为设置length大于当前元素个数,则数组的成员数量会增加到这个值,新增的位置填入“undefined”。

var ff=["a", "b", "c", 1, 2, 4, 5, 6];
ff.length=10;
ff //["a", "b", "c", 1, 2, 4, 5, 6, undefined × 2]

如果人为设置length为不合法的值,Javascript会报错。
值得注意的是,由于数组本质上时对象的一种,所以我们可以为数组添加属性,但这不影响length属性的值。
var a[];
a[“p”]=”abc”
a.length  //0

使用delete删除一个值,会形成空位。但不影响length属性。
var a=[1,2,3];
delete a[1];
a  //[1,undefined,3]
a.length//3

也就是说,length属性不过滤undefined的值。所以,使用length属性进行数组遍历,一定要非常小心。
空位通过空值生成,还是通过显式设为undefined生成,有一个细微的差别。如果通过空值生成,使用数组的forEach方法或者for...in结构进行遍历,空位就会被跳过。如果空位是通过显式定义undefined生成,遍历的时候就不会被跳过。
注意:for-in会遍历数组所有的键,即使是非数字键。所以,使用for-in遍历数组的时候,一定要小心。

ff=["a", "b", "c", 1, 2, 4, 5, 6, undefined × 2]
ff[“p”]=”abc”;
for(item in ff){
console.log(item);
}
//0 1 2 3 4 5 6 7 p.
包括通过Array.prototype定义的任何属性和方法,通过for-in也会遍历到:
Array.prototype.h="ss";
for(item in ff){
console.log(item);
}    //0 1 2 3 4 5 6 7 p,h.

3.数组的检测

自ECMAScript3做出规定以后,就出现了确定某个对象是不是数组的经典问题。对于一个网页,或者一个全局作用域而言,使用instanceof操作符能得到满意的结果:

<span style="font-size:18px;">object instanceof Array</span>


Instanceof的问题在于,它假定单一的全局执行环境。如果网页中包含多个框架,那实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的Array构造函数。如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。

为了解决这个问题,ECMAScript5新增了Array.isArray()方法。

支持这个方法的浏览器有:IE9+,Firefox4+,Safari5+和chrome。对于不支持的浏览器,可以采用以下方法实现:

大家知道,在任何值上调用Object原生的toString()方法,都会返回一个[Object NativeconstructorName]格式的字符串。每个类在内部都有一个[[Class]]属性指定了上述字符串中的构造函数。比如,value是一个Array。则:

<span style="font-size:18px;">Object.prototype.toString.call(value);  //"[object Array]"</span>

所以可以通过下面的方法实现检测数组:

<span style="font-size:18px;">function isArray(value){
return Object.prototype.toString().call(value)== "[object Array]".
}</span>


4.数组的方法

4.1转换方法

所有对象都具有toLocaleString()、toString()和valueof()方法。其中,调用数组的toString()方法会返回有数组中每个值的字符串形式拼接而成的一个一逗号分隔的字符串。而调用valueOf()返回的还是数组。实际上,为了创建这个字符串会调用数组每一项的toString()方法。
使用join()方法,可以使用不同的分隔符来构建这个字符串。Join()方法只接收一个参数,即用作分隔符的字符串,然后返回包含所有数组项的字符串:

var a=[1,2,3];
a.join("|");//"1|2|3"

4.2栈方法

push()可以接收任意数量的参数,把它们逐个添加到数组的末尾,并返回数组的长度。

pop()从数组末尾移除最后一项,减少数组的length值,返回移除的值。

4.3队列方法

shift()——移除数组中的第一个项并返回该项,同时数组长度减一。结合使用shift()和push()方法,可以像使用队列一样使用数组。

unshift()方法,与shift()的用途相反。在数组前端添加任意个项并返回新数组的长度。结合使用unshift()和pop()方法,可以从相反的方向来模拟队列,即在数组的前端添加项,在数组末端移除项。

4.4.重排序方法:

sort()——为了实现排序,sort()会调用数组项的toString()方法,然后比较字符串。即使数组中的每一项都是数值,sort()比较的也是字符串。

[1,23,3,2,4,31].sort();
[1, 2, 23, 3, 31, 4]。


显然,这种排序方式在很多情况下都不是最佳方案。因此sort()方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。

[
{ name: "张三", age: 30 },
{ name: "李四", age: 24 },
{ name: "王五", age: 28  }
].sort(function(o1, o2) {
return o1.age - o2.age;
})
// [
//    { name: "李四", age: 24 },
//    { name: "王五", age: 28  },
//    { name: "张三", age: 30 }
// ]


reverse()——反转原数组的顺序:
[1,23,3,2,4,31].reverse();// [31, 4, 2, 3, 23, 1]

4.5操作方法:

Concat()将新数组的成员,添加到原数组的尾部。然后返回一个新数组,常用于连接多个数组。
["hello"].concat(["world"])//// ["hello", "world"]
Concat()的参数可以是一个或多个数组,也可以是原始类型的值。
如果不提供参数,concat()返回当前数组的一个浅拷贝——如果数组成员包括符合类型的值(比如对象),则新数组拷贝的是该值的引用。
var o = {a:1};
var oldArray = [o];
var newArray = oldArray.concat();
o.a = 2;
newArray[0].a // 2

事实上,只要原数组的成员中包含对象,concat方法不管有没有参数,总是返回该对象的引用。

slice()方法截取数组,得到一个新数组。直接看例子:

var values=[1,2,3,4];
var values2=values.slice(1);//2,3,4


两个参数时,后一个参数表示结束位置,不包括结束位置。
如果slice()的参数中有一个负数,则用数组长度加上该数组来确定相应的位置。例如,在一个包含5项的数组上调用slice(-2,-1)与调用slice(3,4)得到的结果相同。如果结束位置小于起始位置,则返回空数组。
slice方法的一个重要应用,是将类似数组的对象转为真正的数组。
Array.prototype.slice.call({0:'a',1:'b',length:2});  //["a", "b"]

splice()——使用的方式有如下三种:
1. 删除:可以删除任意数量的项,只需指定2个参数:要删除的第一项的位置和要删除的项数。比如:splice(0,2)会删除数组中的前两项。
2.插入:可以向指定位置插入任意数量的项,只需提供3个参数:起始位置,0(要删除的项数)和要插入的项。如果要插入多个项,可以再传入第4,5,以及任意多个项。
3.替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定3个参数:起始位置,要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例如,splice(2,1,“red”,”green”)会删除当前数组位置2的项,然后从位置2开始插入字符串“red”和“green”。
splice()始终返回一个数组——包含从原始数组中删除的项。

4.6位置方法

ECMAScript5为数组实例添加了两个位置方法:indexOf()和LasIndexOf();这两个方法都接收两个参数:要查找的项和(可选的)表示查找起始点位置的索引。
返回要查找的项在数组中的位子。没有则返回-1.
支持的浏览器包括IE9+、Firefox2+、Safari 3+,Opera 9.5+和chrome。

4.7迭代方法

ECMAScript5为数组定义了5个迭代方法。每个方法都接收两个参数:要在每一项上运行的函数和(可选的)运行该函数的作用域对象——影响this的值。传入这些方法中的函数会接收三个参数:数组项的值、该项在数组中的位置和数组对象本身。

every():对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true。
filter():对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组
forEach():对数组中的每一项运行给定函数,这个方法没有返回值。
map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
some():对数组中的每一项运行给定函数,如果该函数对任一项返回true,则返回true。
var ff=["a", "b", "c", 1, 2, 4, 5, 6];
------------------------------------------------------------------
ff.every(function(item,index,array){
return ((typeof item)=="number");
});  //false;
------------------------------------------------------------------
ff.filter(function(item,index,array){
return ((typeof item)=="number");
});  //[1, 2, 4, 5, 6]
------------------------------------------------------------------
a.forEach(function(item,index,array){
console.log(item*2);});//2 4 6
------------------------------------------------------------------
ff.map(function(item,index,array){
return item*2;});//[NaN, NaN, NaN, 2, 4, 8, 10, 12]
------------------------------------------------------------------
ff.some(function(item,index,array){
return ((typeof item)=="number");
});//true

支持这些迭代方法的浏览器有IE9+,Firefox2+,Safari 3+,Opera 9.5+和Chrome。

4.8缩小方法

ECMAScript5还增加了两个缩小数组的方法:reduce()和reduceRight()。这两个方法都会迭代数组的所有项,然后构建一个最终返回的值。其中,reduce()方法从数组的第一项开始,逐个遍历到最后。而reduceRight相反。
reduce方法的第一个参数是一个处理函数。该函数接受四个参数,分别是:
用来累计的变量(即当前状态)
数组的当前元素
当前元素在数组中的序号(从0开始)
原数组
这四个参数之中,只有前两个是必须的,后两个则是可选的。
[1, 2, 3, 4, 5].reduce(function(x, y){
return x+y;
});// 15

利用reduce方法,可以写一个数组求和的sum方法。

Array.prototype.sum = function (){
return this.reduce(function (partial, value){
return partial + value;
})
};
[3,4,5,6,10].sum()
// 28


如果要对累计变量指定初值,可以把它放在reduce方法的第二个参数。
[1, 2, 3, 4, 5].reduce(function(x, y){
return x+y;
}, 10);// 25

由于reduce方法依次处理每个元素,所以实际上还可以用它来搜索某个元素。比如,下面代码是找出长度最长的数组元素。
function findLongest(entries) {
return entries.reduce(function (longest, entry) {
return entry.length > longest.length ? entry : longest;
}, '');
}


除此之外,还可以给Array自定义方法。
Array.prototype.findLongest=function(){
return this.reduce(function(longest,entry){
return entry.length>longest.length?entry:longest;},'');
}

所有的数组就都可以使用这个findLongest方法。

参考资料:
1.《Javascript高级程序设计(第三版)》
2.
Javascript标准参考教程——Array对象
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: