內容要點:編程
ES5中定義了9個新的數組方法來遍歷、映射、過濾、檢測、簡化和搜索數組。數組
概述:首先,大多數方法的第一個參數接收一個函數,而且對數組的每一個元素(或一個元素)調用一次該函數。函數式編程
若是是稀疏數組,對不存在的元素不調用傳遞的函數。函數
在大多數狀況下,調用提供的函數使用三個參數:數組元素、元素的索引和數組自己。優化
一般,只須要第一個參數值,能夠忽略後兩個參數。大多數ES5數組的方法的第一個參數是一個函數,第二個參數是可選的。若是有第二個參數,則調用的函數被看作是第二個參數的方法。this
也就是說,在調用函數時傳遞進去的第二個參數做爲它的this關鍵字的值來使用。spa
被調用的函數的返回值很是重要,可是不一樣的方法處理返回值的方法也不同。ES5中的數組方法都不會修改它們調用的原始數值。對象
固然,傳遞給這些方法的函數是能夠修改這些數組的。索引
一.forEach()數學
forEach()方法從頭到尾遍歷數組,爲每一個元素調用指定的函數。
如上所述,傳遞的函數做爲forEach()的第一個參數。而後forEach()使用三個參數調用該函數:數組元素、元素的索引和數組自己,
若是隻關心數組元素的值,能夠編寫只有一個參數的函數--額外的參數將忽略:
var data = [1,2,3,4,5]; //要求和的數組
//計算數組元素的和值
var sum = 0; //初始爲0
data.forEach(function(value){ sum+=value; }); //將每一個值累加到sum上
sum //=>15
//每一個數組元素的值自加1
data.forEach(function(v,i,a){ a[i] = v + 1; })
data //=>[2,3,4,5,6]
注意,forEach()沒法在全部元素都傳遞給調用的函數以前終止遍歷。
也就是說,沒有像for循環中使用的相應的break語句。若是要提早終止,必須把forEach()方法放在一個try塊中,並能拋出一個異常。
若是forEach()調用的函數拋出foreach.break異常,循環會提早終止。
function foreach(a,f,t){
try{ a.forEach(f,t); }
catch(e){ if( e ===foreach.break ) return;
else throw e;
}
}
foreach.break = new Error("StopIteration");
二.map()
map()方法將調用的數組的每一個元素傳遞給指定的函數,並返回一個數組,它包含該函數的返回值。
例如,
a = [1,2,3];
b = a.map(function(){ return x*x }); //b是[1,4,9]
傳遞給map()的函數的調用方法給forEach()的函數的調用方式同樣。但傳遞給map()的函數應該有返回值。注意,map()返回的是新數組:它不修改調用的數組。
若是是稀疏數組,返回的也是相同方式的稀疏數組:它具備相同的長度,相同的缺失元素。
三.filter()
filter()方法返回的數組元素是調用的數組的一個子集。
傳遞的函數是用來邏輯判斷的:該函數返回true或false。調用判斷函數就像調用forEach()和map()同樣。
若是返回值爲true或能轉化爲true的值,那麼傳遞給斷定函數的元素就是這個子集的成員,它將被添加到一個做爲返回值的數組中。
例如:
a = [5,4,3,2,1];
smallvalues = a.filter( function(x) { return x<3 } ); //[2,1]
everyother = a.filter( function(x,i){ return i%2==0 } ); //[5,3,1]
注意,filter()會跳過稀疏數組中缺乏的元素,它的返回值老是稠密的,爲了壓縮稀疏數組的空缺,代碼以下:
var dense = sparse.filter( function(){ return true; } );
甚至,壓縮空缺並刪除undefined和null元素,能夠這樣使用filter():
a = a.filter( function(x) { return x !== undefined && x!=null; } );
四.every()和some()
every()和some()方法是數組的邏輯斷定:它們對數組元素應用指定的函數進行斷定,返回true或false。
every()方法就像數學中的 "針對全部" 的量詞:當且僅當針對數組中的全部元素調用判斷函數都返回true,它才返回true:
a = [1,2,3,4,5]
a.every( function(x) { return x <10; } ) //=>true,
a.every( function(x) { return x%2===0; } ) //=>false:不是全部的值都是偶數
some()方法就像數學中的"存在"的量詞:當數組中至少有一個元素調用斷定函數返回true,它就返回true;而且當且僅當數值中的全部元素調用判斷函數都返回false,它才返回false:
a = [1,2,3,4,5];
a.some( function(x){ return x%2===0; } ) //=>true
a.some(isNaN) //=>false:a不包含非數組元素
五.reduce()和reduceRight()
reduce()和reduceRight()方法使用指定的函數將數組元素進行組合,生成單個值。這在函數式編程中是常見的操做,也能夠稱爲"注入"和"摺疊"。
例如:
var a = [1,2,3,4,5];
var sum = a.reduce( function(x,y) { return x+y },0 ); //數組求和
var product = a.reduce( function(x,y){ return x*y },1 ); //數組求積
var max = a.reduce( function( x,y ){ return (x>y)?x:y; } ); //求最大值
reduce()須要兩個參數。第一個是執行化簡操做的函數。化簡函數的任務就是用某種方法把兩個值組合或化簡爲一個值,並返回化簡後的值。
在上述例子中,函數經過加法、乘法或取最大值的方法組合兩個值。第二個(可選)參數是一個傳遞給函數的初始值。
reduce()使用的函數與forEach()和map()使用的函數不一樣。比較熟悉的是:
數組元素的索引和數組自己將做爲第2-4個參數傳遞給函數。
第一個參數是到目前爲止的化簡操做積累的結果。第一次調用函數時,第一個參數就是初始值,它就是傳遞reduce()的第二個參數。在接下來的調用中,這個值就是上一次化簡函數的返回值。
在上面的第一個例子中,第一次調用化簡函數時的參數是0和1.將二者相加並返回1.再次調用時的參數是1和2,它返回3.
而後計算3+3=六、6+4=10,最後計算10+5=15.最後的值是15,reduce()返回這個值。
上面第三次調用reduce()時只有一個參數:沒有指定初始值。當不指定初始值調用reduce()時,它將使用數組的第一個元素做爲其初始值。
當不指定初始值調用reduce()時,它將使用數組的第一個元素做爲其初始值。這意味着第一次調用化簡函數就使用了第一次和第二個數組元素做爲其第一個和第二個參數。在上面求和與求積德例子中,能夠省略初始化參數。
在空數組上,不帶初始值參數調用reduce()將致使類型錯誤異常。若是調用它的時候只有一個值--數組只有一個元素而且沒有指定初始值,或者有一個空數組而且指定一個初始值--reduce()只是簡單地返回那個值而不會調用化簡函數。
reduceRight()的工做原理和reduce()同樣,不一樣的是它按照數組索引從高到低(從左到右)處理數組,而不是從低到高。
若是化簡操做的優化順序是從右到左,你可能想使用它,例如:
var a = [2,3,4];
//計算2^(3^4).乘方操做的優先順序是從右到左
var big = a.reduceRight( function( accumulator,value ){ return Math.pow(value,accumulator); } );
注意,reduce()和reduceRight()都能接收一個可選的參數,它指定了化簡函數調用時的this關鍵字的值。可選的初始值參數仍然須要佔一個位置。
值得注意的是,上面描述的every()和some()方法是一種類型的數組化簡操做。可是不一樣的是,它們會盡早終止遍歷而不老是訪問每個數組元素。
當兩個對象擁有同名的屬性時,union()函數使用第一個參數的屬性值。這樣,reduce()和reduceRight()在使用union()時給出了不一樣的結果。
var objects = [{x:1,a:1},{y:2,a:2},{z:3,a:3}];
var leftunion = objects.reduce( union ); //{ x:1,y:2,z:3,a:1 }
var rightunion = objects.reduceRight( union ); //{ x:1,y:2,z:3,a:3 }
六.indexOf()和lastIndexOf()
indexOf()和lastIndexOf()搜索整個數組具備給定值的元素,返回找到的第一個元素的索引或者若是沒有找到就返回-1.indexOf()從頭到尾搜索,而lastIndexOf()則反向搜索。
a = [0,1,2,1,0];
a.indexOf(1) //=>:a[1]是1
a.lastIndexOf(1) //=>3:a[3]是1
a.indexOf(3) //=>-1:沒有值爲3的元素
不一樣於本節描述的其餘方法,indexOf()和lastIndexOf()方法不接收一個函數做爲其參數。
第一個參數是須要搜索的值,第二個參數是可選的:它指定數組中的一個索引,從那裏開始搜索。若是省略該參數,indexOf()從頭開始搜索,而lastIndexOf()從末尾開始搜索。
第二個參數也能夠是負數,它表明相對數組末尾的偏移量,對於splice()方法:例如,-1指定數組的最後一個元素。
以下函數在一個數組中搜索指定的值並返回包含全部匹配的數組索引的一個數組。
//在數組中查找全部出現的x,並返回一個包含匹配索引的數組
function findall(a,x){
var 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; //返回包含索引的數組
}