join()
Array.join()方法將數(shù)組中所有元素都轉(zhuǎn)化為字符串并連接在一起,返回最后生成的字符串??梢灾付ㄒ粋€(gè)可選的字符串在生成的字符串中來(lái)分隔數(shù)組的各個(gè)元素。如果不指定分隔符,默認(rèn)使用逗號(hào)。如以下代碼所示:
var a = [1,2,3]; //創(chuàng)建一個(gè)包含三個(gè)元素的數(shù)組
a.join(); //=>"1,2,3"
a.join(" "); //=>"1 2 3"
a.join(""); //=>"123"
var b = new Array(10); //長(zhǎng)度為10的空數(shù)組
b.join('-') //=>'---------':9個(gè)連字號(hào)組成的字符串
Array.join()方法是String.split()方法的逆向操作,后者是將字符串分割成若干塊來(lái)創(chuàng)建一個(gè)數(shù)組。
reverse()
Array.reverse()方法將數(shù)組中的元素顛倒順序,返回逆序的數(shù)組。它采取了替換;換句話說(shuō),它不通過(guò)重新排列的元素創(chuàng)建新的數(shù)組,而是在原先的數(shù)組中重新排列它們。例如,下面的代碼使用reverse()和join()方法生成字符串“3,2,1”:
var a = [1,2,3];
a.reverse().join(); //=>"3,2,1",并且現(xiàn)在的a是[3,2,1]
sort()
Array.sort()方法將數(shù)組中的元素排序并返回排序后的數(shù)組。當(dāng)不帶參數(shù)調(diào)用sort()時(shí),數(shù)組元素以字母表順序排序(如有必要將臨時(shí)轉(zhuǎn)化為字符串進(jìn)行比較):
var a = new Array("banana", "cherry", "apple");
a.sort();
var s = a.join(","); //s=="apple,banana,cherry"
如果數(shù)組包含undefined元素,它們會(huì)被排到數(shù)組的尾部。
為了按照其他方式而非字母表順序進(jìn)行數(shù)組排序,必須給sort()方法傳遞一個(gè)比較函數(shù)。該函數(shù)決定了它的兩個(gè)參數(shù)在排好序的數(shù)組中的先后順序。假設(shè)第一個(gè)參數(shù)應(yīng)該在前,比較函數(shù)應(yīng)該返回一個(gè)小于0的數(shù)值。反之,假設(shè)第一個(gè)參數(shù)應(yīng)該在后,函數(shù)應(yīng)該返回一個(gè)大于0的數(shù)值。并且,假設(shè)兩個(gè)值相等(也就是說(shuō),它們的順序無(wú)關(guān)緊要),函數(shù)應(yīng)該返回0。因此,例如,用數(shù)值大小而非字母表順序進(jìn)行數(shù)組排序,代碼如下:
var a = [33, 4, 1111, 222];
a.sort(); //字母表順序:1111,222,33,4
a.sort(function(a, b) { //數(shù)值順序:4,33,222,1111
return a - b; //根據(jù)順序,返回負(fù)數(shù)、0、正數(shù)
});
a.sort(function(a, b) {return b-a});//數(shù)值大小相反的順序
注意,這里使用匿名函數(shù)表達(dá)式非常方便。既然比較函數(shù)只使用一次,就沒(méi)必要給它們命名了。
另外一個(gè)數(shù)組元素排序的例子,也許需要對(duì)一個(gè)字符串?dāng)?shù)組執(zhí)行不區(qū)分大小寫(xiě)的字母表排序,比較函數(shù)首先將參數(shù)都轉(zhuǎn)化為小寫(xiě)字符串(使用toLowerCase()方法),再開(kāi)始比較:
a = ['ant', 'Bug', 'cat', 'Dog'];
a.sort(); //區(qū)分大小寫(xiě)的排序:['Bug','Dog','ant',cat']
a.sort(function(s, t) { //不區(qū)分大小寫(xiě)的排序
var a = s.toLowerCase();
var b = t.toLowerCase();
if (a < b) return -1;
if (a > b) return 1;
return 0;
}); //=>['ant','Bug','cat','Dog']
concat()
Array.concat()方法創(chuàng)建并返回一個(gè)新數(shù)組,它的元素包括調(diào)用concat()的原始數(shù)組的元素和concat()的每個(gè)參數(shù)。如果這些參數(shù)中的任何一個(gè)自身是數(shù)組,則連接的是數(shù)組的元素,而非數(shù)組本身。但要注意,concat()不會(huì)遞歸扁平化數(shù)組的數(shù)組。concat()也不會(huì)修改調(diào)用的數(shù)組。下面有一些示例:
var a = [1, 2, 3];
a.concat(4, 5); //返回[1,2,3,4,5]
a.concat([4, 5]); //返回[1,2,3,4,5]
a.concat([4, 5], [6, 7]); //返回[1,2,3,4,5,6,7]
a.concat(4, [5, [6, 7]]); //返回[1,2,3,4,5,[6,7]]
slice()
Array.slice()方法返回指定數(shù)組的一個(gè)片段或子數(shù)組。它的兩個(gè)參數(shù)分別指定了片段的開(kāi)始和結(jié)束的位置。返回的數(shù)組包含第一個(gè)參數(shù)指定的位置和所有到但不含第二個(gè)參數(shù)指定的位置之間的所有數(shù)組元素。如果只指定一個(gè)參數(shù),返回的數(shù)組將包含從開(kāi)始位置到數(shù)組結(jié)尾的所有元素。如參數(shù)中出現(xiàn)負(fù)數(shù),它表示相對(duì)于數(shù)組中最后一個(gè)元素的位置。例如,參數(shù)-1指定了最后一個(gè)元素,而-3指定了倒數(shù)第三個(gè)元素。注意,slice()不會(huì)修改調(diào)用的數(shù)組。下面有一些示例:
var a = [1, 2, 3, 4, 5];
a.slice(0, 3); //返回[1,2,3]
a.slice(3); //返回[4,5]
a.slice(1, -1); //返回[2,3,4]
a.slice(-3, -2); //返回[3]
splice()
Array.splice()方法是在數(shù)組中插入或刪除元素的通用方法。不同于slice()和concat(),splice()會(huì)修改調(diào)用的數(shù)組。注意,splice()和slice()擁有非常相似的名字,但它們的功能卻有本質(zhì)的區(qū)別。
splice()能夠從數(shù)組中刪除元素、插入元素到數(shù)組中或者同時(shí)完成這兩種操作。在插入或刪除點(diǎn)之后的數(shù)組元素會(huì)根據(jù)需要增加或減小它們的索引值,因此數(shù)組的其他部分仍然保持連續(xù)的。splice()的第一個(gè)參數(shù)指定了插入和(或)刪除的起始位置。第二個(gè)參數(shù)指定了應(yīng)該從數(shù)組中刪除的元素的個(gè)數(shù)。如果省略第二個(gè)參數(shù),從起始點(diǎn)開(kāi)始到數(shù)組結(jié)尾的所有元素都將被刪除。splice()返回一個(gè)由刪除元素組成的數(shù)組,或者如果沒(méi)有刪除元素就返回一個(gè)空數(shù)組。例如:
var a = [1, 2, 3, 4, 5, 6, 7, 8];
a.splice(4); //返回[5,6,7,8];a是[1,2,3,4]
a.splice(1, 2); //返回[2,3];a是[1,4]
a.splice(1, 1); //返回[4];a是[1]
splice()的前兩個(gè)參數(shù)指定了需要?jiǎng)h除的數(shù)組元素。緊隨其后的任意個(gè)數(shù)的參數(shù)指定了需要插入到數(shù)組中的元素,從第一個(gè)參數(shù)指定的位置開(kāi)始插入。例如:
var 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','b'];a是[1,2,[1,2],3,3,4,5]
注意,區(qū)別于concat(),splice()會(huì)插入數(shù)組本身而非數(shù)組的元素。
push()和pop()
push()和pop()方法允許將數(shù)組當(dāng)做棧來(lái)使用。push()方法在數(shù)組的尾部添加一個(gè)或多個(gè)元素,并返回?cái)?shù)組新的長(zhǎng)度。pop()方法則相反:它刪除數(shù)組的最后一個(gè)元素,減小數(shù)組長(zhǎng)度并返回它刪除的值。注意,兩個(gè)方法都修改并替換原始數(shù)組而非生成一個(gè)修改版的新數(shù)組。組合使用push()和pop()能夠用JavaScript數(shù)組實(shí)現(xiàn)先進(jìn)后出的棧。例如:
var stack = []; //stack:[]
stack.push(1, 2); //stack:[1,2] 返回2
stack.pop(); //stack:[1] 返回2
stack.push(3); //stack:[1,3] 返回2
stack.pop(); //stack:[1] 返回3
stack.push([4, 5]); //stack:[1,[4,5]] 返回2
stack.pop(); //stack:[1] 返回[4,5]
stack.pop(); //stack:[] 返回1
unshift()和shift()
unshift()和shift()方法的行為非常類似于push()和pop(),不一樣的是前者是在數(shù)組的頭部而非尾部進(jìn)行元素的插入和刪除操作。unshift()在數(shù)組的頭部添加一個(gè)或多個(gè)元素,并將已存在的元素移動(dòng)到更高索引的位置來(lái)獲得足夠的空間,最后返回?cái)?shù)組新的長(zhǎng)度。shift()刪除數(shù)組的第一個(gè)元素并將其返回,然后把所有隨后的元素下移一個(gè)位置來(lái)填補(bǔ)數(shù)組頭部的空缺。例如:
var a = []; //a:[]
a.unshift(1); //a:[1]返回:1
a.unshift(22); //a:[22,1]返回:2
a.shift(); //a:[1]返回:22
a.unshift(3, [4, 5]); //a:[3,[4,5],1]返回:3
a.shift(); //a:[[4,5],1]返回:3
a.shift(); //a:[1]返回:[4,5]
a.shift(); //a:[]返回:1
注意,當(dāng)使用多個(gè)參數(shù)調(diào)用unshift()時(shí)它的行為令人驚訝。參數(shù)是一次性插入的(就像splice()方法)而非一次一個(gè)地插入。這意味著最終的數(shù)組中插入的元素的順序和它們?cè)趨?shù)列表中的順序一致。而假如元素是一次一個(gè)地插入,它們的順序應(yīng)該是反過(guò)來(lái)的。
toString()和toLocaleString()
數(shù)組和其他JavaScript對(duì)象一樣擁有toString()方法。針對(duì)數(shù)組,該方法將其每個(gè)元素轉(zhuǎn)化為字符串(如有必要將調(diào)用元素的toString()方法)并且輸出用逗號(hào)分隔的字符串列表。注意,輸出不包括方括號(hào)或其他任何形式的包裹數(shù)組值的分隔符。例如:
[1,2,3].toString(); //生成'1,2,3'
["a","b","c"].toString(); //生成'a,b,c'
[1,[2,'c']].toString(); //生成'1,2,c'
注意,這里與不使用任何參數(shù)調(diào)用join()方法返回的字符串是一樣的。
toLocaleString()是toString()方法的本地化版本。它調(diào)用元素的toLocaleString()方法將每個(gè)數(shù)組元素轉(zhuǎn)化為字符串,并且使用本地化(和自定義實(shí)現(xiàn)的)分隔符將這些字符串連接起來(lái)生成最終的字符串。
forEach()
forEach()方法從頭至尾遍歷數(shù)組,為每個(gè)元素調(diào)用指定的函數(shù)。如上所述,傳遞的函數(shù)作為forEach()的第一個(gè)參數(shù)。然后forEach()使用三個(gè)參數(shù)調(diào)用該函數(shù):數(shù)組元素、元素的索引和數(shù)組本身。如果只關(guān)心數(shù)組元素的值,可以編寫(xiě)只有一個(gè)參數(shù)的函數(shù)——額外的參數(shù)將忽略:
var data = [1, 2, 3, 4, 5]; //要求和的數(shù)組
//計(jì)算數(shù)組元素的和值
var sum = 0; //初始為0
data.forEach(function(value) {sum += value;}); //將每個(gè)值累加到sum上
sum; //=>15//每個(gè)數(shù)組元素的值自加1
data.forEach(function(v, i, a) {a[i] = v + 1;});
data; //=>[2,3,4,5,6]
map()
map()方法將調(diào)用的數(shù)組的每個(gè)元素傳遞給指定的函數(shù),并返回一個(gè)數(shù)組,它包含該函數(shù)的返回值。例如:
a = [1, 2, 3];
b = a.map(function(x) {return x * x;}); //b是[1,4,9]
傳遞給map()的函數(shù)的調(diào)用方式和傳遞給forEach()的函數(shù)的調(diào)用方式一樣,但傳遞給map()的函數(shù)應(yīng)該有返回值。注意,map()返回的是新數(shù)組:它不修改調(diào)用的數(shù)組。如果是稀疏數(shù)組,返回的也是相同方式的稀疏數(shù)組:它具有相同的長(zhǎng)度,相同的缺失元素。
filter()
filter()方法返回的數(shù)組元素是調(diào)用的數(shù)組的一個(gè)子集。傳遞的函數(shù)是用來(lái)邏輯判定的:該函數(shù)返回true或false,調(diào)用判定函數(shù)就像調(diào)用forEach()和map()一樣。如果返回值為true或能轉(zhuǎn)化為true的值,那么傳遞給判定函數(shù)的元素就是這個(gè)子集的成員,它將被添加到一個(gè)作為返回值的數(shù)組中。例如:
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()會(huì)跳過(guò)稀疏數(shù)組中缺少的元素,它的返回?cái)?shù)組總是稠密的。為了壓縮稀疏數(shù)組的空缺,代碼如下:
var dense = sparse.filter(function() {return true;});
甚至,壓縮空缺并刪除undefined和null元素,可以這樣使用filter():
a = a.filter(function(x) {return x !== undefined && x != null;});
every()和some()
every()和some()方法是數(shù)組的邏輯判定:它們對(duì)數(shù)組元素應(yīng)用指定的函數(shù)進(jìn)行判定,返回true或false。
every()方法就像數(shù)學(xué)中的“針對(duì)所有”的量詞:當(dāng)且僅當(dāng)針對(duì)數(shù)組中的所有元素調(diào)用判定函數(shù)都返回true,它才返回true:
a = [1, 2, 3, 4, 5];
a.every(function(x) {return x < 10;}); //=>true:所有的值<10
a.every(function(x) {return x % 2 === 0;}); //=>false:不是所有的值都是偶數(shù)
some()方法就像數(shù)學(xué)中的“存在”的量詞:當(dāng)數(shù)組中至少有一個(gè)元素調(diào)用判定函數(shù)返回true,它就返回true;并且當(dāng)且僅當(dāng)數(shù)值中的所有元素調(diào)用判定函數(shù)都返回false,它才返回false:
a = [1, 2, 3, 4, 5];
a.some(function(x) {return x % 2 === 0;}); //=>true:a含有偶數(shù)值
a.some(isNaN); //=>false:a不包含非數(shù)值元素
注意,一旦every()和some()確認(rèn)該返回什么值它們就會(huì)停止遍歷數(shù)組元素。some()在判定函數(shù)第一次返回true后就返回true,但如果判定函數(shù)一直返回false,它將會(huì)遍歷整個(gè)數(shù)組。every()恰好相反:它在判定函數(shù)第一次返回false后就返回false,但如果判定函數(shù)一直返回true,它將會(huì)遍歷整個(gè)數(shù)組。注意,在空數(shù)組上調(diào)用時(shí),every()返回true,some()返回false。
reduce()和reduceRight()
reduce()和reduceRight()方法使用指定的函數(shù)將數(shù)組元素進(jìn)行組合,生成單個(gè)值。這在函數(shù)式編程中是常見(jiàn)的操作,也可以稱為“注入”和“折疊”。舉例說(shuō)明它是如何工作的:
var a = [1, 2, 3, 4, 5]
var sum = a.reduce(function(x, y) {return x + y}, 0); //數(shù)組求和
var product = a.reduce(function(x, y) {return x * y},1); //數(shù)組求積
var max = a.reduce(function(x, y) {return(x > y) ? x : y;}); //求最大值
reduce()需要兩個(gè)參數(shù)。第一個(gè)是執(zhí)行化簡(jiǎn)操作的函數(shù)?;?jiǎn)函數(shù)的任務(wù)就是用某種方法把兩個(gè)值組合或化簡(jiǎn)為一個(gè)值,并返回化簡(jiǎn)后的值。在上述例子中,函數(shù)通過(guò)加法、乘法或取最大值的方法組合兩個(gè)值。第二個(gè)(可選)的參數(shù)是一個(gè)傳遞給函數(shù)的初始值。
reduce()使用的函數(shù)與forEach()和map()使用的函數(shù)不同。比較熟悉的是,數(shù)組元素、元素的索引和數(shù)組本身將作為第2~4個(gè)參數(shù)傳遞給函數(shù)。第一個(gè)參數(shù)是到目前為止的化簡(jiǎn)操作累積的結(jié)果。第一次調(diào)用函數(shù)時(shí),第一個(gè)參數(shù)是一個(gè)初始值,它就是傳遞給reduce()的第二個(gè)參數(shù)。在接下來(lái)的調(diào)用中,這個(gè)值就是上一次化簡(jiǎn)函數(shù)的返回值。在上面的第一個(gè)例子中,第一次調(diào)用化簡(jiǎn)函數(shù)時(shí)的參數(shù)是0和1。將兩者相加并返回1。再次調(diào)用時(shí)的參數(shù)是1和2,它返回3。然后它計(jì)算3+3=6、6+4=10,最后計(jì)算10+5=15。最后的值是15,reduce()返回這個(gè)值。
可能已經(jīng)注意到了,上面第三次調(diào)用reduce()時(shí)只有一個(gè)參數(shù):沒(méi)有指定初始值。當(dāng)不指定初始值調(diào)用reduce()時(shí),它將使用數(shù)組的第一個(gè)元素作為其初始值。這意味著第一次調(diào)用化簡(jiǎn)函數(shù)就使用了第一個(gè)和第二個(gè)數(shù)組元素作為其第一個(gè)和第二個(gè)參數(shù)。在上面求和與求積的例子中,可以省略初始值參數(shù)。
在空數(shù)組上,不帶初始值參數(shù)調(diào)用reduce()將導(dǎo)致類型錯(cuò)誤異常。如果調(diào)用它的時(shí)候只有一個(gè)值——數(shù)組只有一個(gè)元素并且沒(méi)有指定初始值,或者有一個(gè)空數(shù)組并且指定一個(gè)初始值——reduce()只是簡(jiǎn)單地返回那個(gè)值而不會(huì)調(diào)用化簡(jiǎn)函數(shù)。
reduceRight()的工作原理和reduce()一樣,不同的是它按照數(shù)組索引從高到低(從右到左)處理數(shù)組,而不是從低到高。
indexOf()和lastIndexOf()
indexOf()和lastIndexOf()搜索整個(gè)數(shù)組中具有給定值的元素,返回找到的第一個(gè)元素的索引或者如果沒(méi)有找到就返回-1。indexOf()從頭至尾搜索,而lastIndexOf()則反向搜索。
a = [0, 1, 2, 1, 0];
a.indexOf(1); //=>1:a[1]是1
a.lastIndexOf(1); //=>3:a[3]是1
a.indexOf(3); //=>-1:沒(méi)有值為3的元素
第一個(gè)參數(shù)是需要搜索的值,第二個(gè)參數(shù)是可選的:它指定數(shù)組中的一個(gè)索引,從那里開(kāi)始搜索。如果省略該參數(shù),indexOf()從頭開(kāi)始搜索,而lastIndexOf()從末尾開(kāi)始搜索。第二個(gè)參數(shù)也可以是負(fù)數(shù),它代表相對(duì)數(shù)組末尾的偏移量。