为了更方便的对Array进行操作,ES5规范在Array的原型上新增了9个方法,分别是forEach、filter、map、reduce、reduceRight、some、every、indexOf 和 lastIndexOf,本文将对这几个方法进行详细的讲解,并对每一个方法进行原型扩展,以兼容不支持ES5的浏览器。
1、forEach (callback[,thisArg])
在ES5之前,我们可以通过for和for in 两种方式来遍历数组,而ES5引入了一个新方法forEach,使数组遍历更加简洁,forEach需要传递2个参数,第一个参数是回调函数,是必选参数,第二个参数是一个对象,用来改变callback中的this指向,是可选参数。
var arr = ['a' ,'b' ,'c' ];
arr.forEach (function (v,i,r) {
console.log(v,i,r);
})
->
a 0 ["a" , "b" , "c" ]
b 1 ["a" , "b" , "c" ]
c 2 ["a" , "b" , "c" ]
从输出的结果可以看出,callback中传入了3个参数v,i,r 分别表示当前元素、当前位置、数组对象。再看看使用 thisArg 的例子:
var obj = {
print :function (a,b) {
console.log(a,b);
}
};
var arr = ['a' ,'b' ,'c' ];
arr.forEach (function (v,i,a) {
this.print (v,i);
},obj);
不传thisArgs时,callback中的 this 默认指向 window 对象,当传递thisArg时,callback中的this就指向了thisArg,因此这个参数的目的就是为了改变回调函数中的this指向。
对于不支持ES5的浏览器,我们可以对forEach进行简单的扩展来兼容老的浏览器:
if (!Array .prototype.forEach){
Array .prototype.forEach = function (callback,thisArg) {
for (var i=0 ;i<this .length;i++){
callback.call(thisArg,this [i],i,this .toString());
}
}
}
2、filter (callback[,thisArg])
filter是`过滤`的意思,所以这个方法的作用就是返回一个匹配过滤条件的新数组,其接收两个参数callback和thisArg, callback也是回调函数,主要用于对元素进行条件匹配,thisArg和forEach中的thisArg作用一样,在这里就不重复了,看下面示例:
var arr = ["a" ,"b" ,"a" ,"c" ];
var newArr = arr.filter(function (item) {
return item === "a" ;
});
newArr -> ["a" ,"a" ]
代码很简单,一看就明白,没有filter的时候,要实现这个功能,我们事先要创建一个空的数组,把匹配到的元素再push进去,现在就不需要那么麻烦了,我们再看看对filter的扩展:
if (!Array .prototype.filter) {
Array .prototype.filter = function (callback, thisArg) {
var temp = [];
for (var i = 0 ; i < this .length; i++) {
if (callback.call(thisArg,this [i])){
temp.push(this [i]);
}
}
return temp;
}
}
3、map (callback[,thisArg])
map的作用是对原数组进行加工处理后并将其作为一个新数组返回,该方法同样接收两个参数,callback是回调函数用于对数组进行加工处理,thisArg和上面的一样。先看一个简单的例子:
var arr = [
{w:10 ,h:10 },
{w:15 ,h:20 },
{w:12 ,h:12 }
];
var newArr = arr.map(function (item) {
item.area = item.w * item.h;
return item;
});
newArr[0 ] - > {w: 10 , h: 10 , area: 100 }
可以看出,newArr返回的是增加了area属性的对象数组。这个方法非常实用,一般情况下,当一个ajax请求返回时,我们都要对其结果集进行过滤和校验等操作,这时map就派上用场了。我们再看看如果对map进行兼容性扩展:
if (!Array .prototype.map) {
Array .prototype.map = function (callback, thisArg) {
var temp = [];
for (var i = 0 ; i < this .length; i++) {
var newItem = callback.call(thisArg,this [i]);
temp.push(newItem);
}
return temp;
}
}
4、reduce (callback[,initialValue])
reduce在这里有`减少`的意思,那reduce到底是干什么用的呢?看看比较官方的解释:The method applies a function against an accumulator and each value of the array (from left -to-right ) to reduce it to a single value . 自己慢慢体会吧,我们先看看怎么使用吧,用的多了自然就明白了:
var arr = [1 ,2 ,3 ,4 ];
var newArr = arr.reduce(function (previousValue, currentValue, currentIndex, array) {
console.log(previousValue, currentValue,currentIndex);
return previousValue + currentValue;
});
1 2 1
3 3 2
6 4 3
newArr -> 10
从运行结果可以看出,reduce实现了数组元素的累加功能,reduce接收4个参数,previousValue存放的是上一次callback返回的结果,currentValue是当前元素,currentIndex是当前元素位置,array是当前数组。previousValue 初始值为数组的第一个元素,数组从第2个元素开始遍历。我们再来看看initialValue 究竟是什么鬼:
var arr = [1 ,2 ,3 ,4 ];
var newArr = arr.reduce(function (previousValue, currentValue, currentIndex, array) {
console.log(previousValue, currentValue,currentIndex);
return previousValue + currentValue;
},100 );
100 1 0
101 2 1
103 3 2
106 4 3
newArr -> 110
从运行结果看,initialValue参数指定了previousValue的初始值,更重要的是,这次数组是从第1个位置开始遍历,而不再是从第2个位置开始了。 现在回过头来,对照这两个例子,我相信你一定能够理解reduce的作用了。下面对于reduce的扩展会巩固你对reduce的理解:
if (!Array .prototype.reduce) {
Array .prototype.reduce = function (callback, initialValue) {
var previousValue = initialValue || this [0 ];
for (var i = initialValue?0 :1 ; i < this .length; i++) {
previousValue = callback(previousValue, this [i],i,this .toString());
}
return previousValue;
}
}
5、reduceRight (callback[,initialValue])
和reduce的作用完全相同,唯一的不同是,reduceRight是从右至左遍历数组的元素。
6、some (callback[,thisArg])
some是`某些、一些`的意思,因此,some的作用是检测数组中的每一个元素,当callback返回true时就停止遍历,并返回true,这样的描述似乎有些抽象,看代码,一切尽在代码中:
var arr = [ 1 , 2 , 3 , 4 ];
var result = arr.some( function ( item, index , array ) );
->
1 0 [1 , 2 , 3 , 4 ]
2 1 [1 , 2 , 3 , 4 ]
3 2 [1 , 2 , 3 , 4 ]
restule -> true
从运行结果看,some检测整个数组,只要当arr中有一个元素符合条件item>2 就停止检测和遍历,并返回true,以表示检测到目标。这和我们在for循环中使用break语言的作用有点类似,这会儿你应该明白some的作用了吧! 下面对于some的扩展会有助于你对some的理解:
if (!Array .prototype.some) {
Array .prototype.some = function (callback, thisArg) {
for (var i = 0 ; i < this .length; i++) {
if (callback.call(thisArg,this [i],i,this .toString())){
return true ;
}
}
return false ;
}
}
7、every (callback[,thisArg])
every是`每一个`的意思,相比some来讲,every对元素的检测更加严格,那every到底是干什么的呢,看代码就知道了:
var arr = [ 1 , 2 , 3 , 4 ];
var result = arr.every( function ( item, index , array ) );
1 0 [1 , 2 , 3 , 4 ]
2 1 [1 , 2 , 3 , 4 ]
3 2 [1 , 2 , 3 , 4 ]
result -> false
从运行结果看,当检测第3个元素时,item<3为false, 停止检测,并返回false,这说明every在检测元素时,要求每一个元素都要符合条件item<3,如果有一个不符合就停止检测,并返回false,(ps:你可以测试item<5时的运行结果,返回值一定是true)。那every到底有什么用武之地呢? 当一个for循环使用了break语句后,我们想知道for循环是否正常的执行完时, 我们一般会通过检测for中的索引i==arr.length来判断,因此every的作用就体现在这里。 我们再看看对于every方法的扩展:
if (!Array .prototype.every) {
Array .prototype.every = function (callback, thisArg) {
for (var i = 0 ; i < this .length; i++) {
if (!callback.call(thisArg,this [i],i,this .toString())){
return false ;
}
}
return true ;
}
}
8、indexOf 和 lastIndexOf
这两个方法和String类中indexOf和lastIndexOf作用类似,相信大家对这两个方法用的很熟了,因此这里不多做解释了。
数组常用的API
1、sort ([compareFunction])
对数组做原地排序,并返回这个数组,默认按照字符串UNICODE的码位点排序,如果指明了compareFunction,则数组会按照调用函数的返回值排序:
var fruit = ['cherries' , 'apples' , 'bananas' ];
fruit.sort();
var scores = [1 , 10 , 2 , 21 ];
scores.sort();
var numbers = [2 ,4 ,1 ,10 ,3 ];
numbers.sort(function (a,b) {
return a-b;
});
numbers.sort(function (a,b) {
return b-a;
});
2、join ([separator])
将数组中的所有元素连接成一个字符串。separtor 用于指定连接每个数组元素的分隔符。分隔符会被转成字符串类型;如果省略的话,默认为一个逗号。如果separtor 是一个空字符串,那么数组中的所有元素将被直接连接。
var data = ['Wind' , 'Rain' , 'Fire' ];
data.join ();
data.join (', ' );
data.join (' + ' );
data.join ('' );
3、concat (value1,…,valueN)
concat 方法将创建一个新的数组,然后将调用它的对象(this 指向的对象)中的元素以及所有参数中的数组类型的参数中的元素以及非数组类型的参数本身按照顺序放入这个新数组,并返回该数组. valueN允许是数组或非数组值.
var alpha = ['a' , 'b' , 'c' ];
alpha.concat(1 , [2 , 3 ]); // ["a" , "b" , "c" , 1 , 2 , 3 ]
4、push (element1,…,elementN) 和 pop ()
push添加一个或多个元素到数组的末尾,并返回数组新的长度,pop删除一个数组中的最后的一个元素,并且返回这个元素。
var data = [1,2,3];
data .push(4,5,6) ; //6 ->数组的长度 data ->[1,2,3,4,5,6]
data .pop() ; //6 ->出栈的元素 data ->[1,2,3,4,5]
注意:push和pop并不会改变原来的元素位置。
5、unshift (element1,…,elementN) 和 shift ()
unshift添加一个或多个元素到数组的开头,并返回数组新的长度,shift删除一个数组中的第一个元素,并且返回这个元素。
var data = [1,2,3];
data .unshift(-1,-2,-3) ; //6->新数组的长度 data ->[-1,-2,-3,1,2,3]
data .shift() ; // -1 ->被移除的元素 data ->[-2,-3,1,2,3]
注意:unshift和shift都会改变原来的元素位置。
6、slice (begin[,end]) 和 splice (start,deleteCount[,value1,…,valueN])
slice方法从begin的索引位置开始提取数组元素,到end位置结束,但不包括end位置的元素,如果end被省略,则默认提取到数组的结尾。splice方法从一个数组中移除一个或多个元素,如果必要,在所移除元素的位置上插入新元素,返回所移除的元素。
var data = [1,2,3];
data .slice(0) ; //[1,2,3] 提取的元素
data .slice(1,2) ; //[2] 提取的元素
data .splice(2,1) ;//[3]->被删除的元素 data ->[1,2]
data .splice(2,2,4,5) ; //[3]->被删除的元素 data ->[1,2,4,5]
data .splice(2,2,4,5,6) ; //[2,3]->被删除的元素 data ->[1,4,5,6]
原文地址