js引用類型2:Array類型

2 Array類型

2.0.1 創(chuàng)建方式
  • 第一種是使用Array 構(gòu)造函數(shù)
let colors = new Array(); //創(chuàng)建一個(gè)空數(shù)組
let colors = new Array(20); //創(chuàng)建length值為20的空數(shù)組
let colors = new Array("red"); //創(chuàng)建length值為1的非空數(shù)組

let colors = Array(3); //可以省略new操作符,然后情況跟new Array()使用方式相同
  • 第二種基本方式是使用數(shù)組字面量表示法
let colors = ["red", "blue", "green"]; // 創(chuàng)建一個(gè)包含3 個(gè)字符串的數(shù)組
let names = []; // 創(chuàng)建一個(gè)空數(shù)組
let values = [1,2,]; // 不要這樣!這樣會(huì)創(chuàng)建一個(gè)包含2 或3 項(xiàng)的數(shù)組
let options = [,,,,,]; // 不要這樣!這樣會(huì)創(chuàng)建一個(gè)包含5 或6 項(xiàng)的數(shù)組

具體原因說一下:因?yàn)镮E8 及之前版本中的ECMAScript 實(shí)現(xiàn)在數(shù)組字面量方面存在bug。IE8及更早的版本,可能會(huì)創(chuàng)建6項(xiàng);在IE9+、Firefox、Opera、Safari 和Chrome 中可能會(huì)創(chuàng)建5項(xiàng)。在像這種省略值的情況下,每一項(xiàng)都將獲得undefined 值;這個(gè)結(jié)果與調(diào)用Array 構(gòu)造函數(shù)時(shí)傳遞項(xiàng)數(shù)在邏輯上是相同的。但是由于IE 的實(shí)現(xiàn)與其他瀏覽器不一致,因此我們強(qiáng)烈建議不要使用這種語(yǔ)法。

2.1檢測(cè)數(shù)組
  • instanceof(適用于只有一個(gè)全局作用域)
if (value instanceof Array){
    //對(duì)數(shù)組執(zhí)行某些操作
};
instanceof 操作符的問題在于,它假定只有一個(gè)全局執(zhí)行環(huán)境。如果網(wǎng)頁(yè)中包含多個(gè)框架,那實(shí)際上就存在兩個(gè)以上不同的全局執(zhí)行環(huán)境,從而存在兩個(gè)以上不同版本的Array 構(gòu)造函數(shù),從而產(chǎn)生錯(cuò)誤檢測(cè)結(jié)果。
  • Array.isArray()
if (Array.isArray(value)){
    //對(duì)數(shù)組執(zhí)行某些操作
};
支持Array.isArray()方法的瀏覽器有IE9+、Firefox 4+、Safari 5+、Opera 10.5+和Chrome。

然后:
由于兩種方法都有各自的局限性,要在尚未實(shí)現(xiàn)這個(gè)方法中的瀏覽器中準(zhǔn)確檢測(cè)數(shù)組,不妨采用下面提供的方法

  • 使用Object.prototype上的原生toString()方法判斷數(shù)據(jù)類型

大家知道,在任何值上調(diào)用Object 原生的toString()方法,都會(huì)返回一個(gè)
[object NativeConstructorName]格式的字符串。每個(gè)類在內(nèi)部都有一個(gè)[[Class]]屬性,這個(gè)屬性中就指定了上述字符串中的構(gòu)造函數(shù)名。舉個(gè)例子吧。

alert(Object.prototype.toString.call(value)); //"[object Array]"

由于原生數(shù)組的構(gòu)造函數(shù)名與全局作用域無關(guān),因此使用toString()就能保證返回一致的值。利用這一點(diǎn),可以創(chuàng)建如下函數(shù):

function isArray(value){
    return Object.prototype.toString.call(value) == "[object Array]";
}

同樣,也可以基于這一思路來測(cè)試某個(gè)值是不是原生函數(shù)或正則表達(dá)式(擴(kuò)展一下)

function isFunction(value){
    return Object.prototype.toString.call(value) == "[object Function]";
}
function isRegExp(value){
    return Object.prototype.toString.call(value) == "[object RegExp]";
}

不過要注意,對(duì)于在IE 中以COM 對(duì)象形式實(shí)現(xiàn)的任何函數(shù),isFunction()都將返回false(因?yàn)樗鼈儾⒎窃腏avaScript 函數(shù))
這一技巧也廣泛應(yīng)用于檢測(cè)原生JSON 對(duì)象。Object 的toString()方法不能檢測(cè)非原生構(gòu)造函數(shù)的構(gòu)造函數(shù)名。因此,開發(fā)人員定義的任何構(gòu)造函數(shù)都將返回[object Object]。有些JavaScript 庫(kù)會(huì)包含與下面類似的代碼。

let isNativeJSON = window.JSON && Object.prototype.toString.call(JSON) == "[object JSON]";

在Web 開發(fā)中能夠區(qū)分原生與非原生JavaScript 對(duì)象非常重要。只有這樣才能確切知道某個(gè)對(duì)象到底有哪些功能。這個(gè)技巧可以對(duì)任何對(duì)象給出正確的結(jié)論。

請(qǐng)注意,Object.prototpye.toString()本身也可能會(huì)被修改。本節(jié)討論的
技巧假設(shè)Object.prototpye.toString()是未被修改過的原生版本。

2.2轉(zhuǎn)換方法

如前所述,所有對(duì)象都具有toLocaleString()、toString()和valueOf()方法。

let colors = ["red", "blue", "green"]; // 創(chuàng)建一個(gè)包含3 個(gè)字符串的數(shù)組
alert(colors.toString()); // "red,blue,green"
alert(colors.valueOf()); // [red,blue,green]
alert(colors.toLocalString()); // "red,blue,green"
alert(colors.join("||")); //"red||green||blue"

先拋出這么多,join方法還是挺有用的。
2.3棧方法 (LIFO:Last-In-First-Out,后進(jìn)先出)

push方法是像數(shù)組末端添加項(xiàng),返回的是數(shù)組長(zhǎng)度;pop方法返回的是取出的最后一項(xiàng);

let colors = new Array(); // 創(chuàng)建一個(gè)數(shù)組
let count = colors.push("red", "green"); // 推入兩項(xiàng)
alert(count); //2  
count = colors.push("black"); // 推入另一項(xiàng)
alert(count); //3
let item = colors.pop(); // 取得最后一項(xiàng)
alert(item); //"black"
alert(colors.length); //2
colors[colors.length] = "yellow"; // 賦值最后一項(xiàng),功能類似push();
alert(colors);  //["red", "green", "yellow"]
2.4隊(duì)列方法 (FIFO:First-In-First-Out,先進(jìn)先出)

實(shí)現(xiàn)這一操作的數(shù)組方法就是shift(),它能夠移除數(shù)組中的第一個(gè)項(xiàng)并返回該項(xiàng),同時(shí)將數(shù)組長(zhǎng)度減1。結(jié)合使用shift()和push()方法,可以像使用隊(duì)列一樣使用數(shù)組。

let colors = new Array(); //創(chuàng)建一個(gè)數(shù)組
let count = colors.push("red", "green"); //推入兩項(xiàng)
alert(count); //2
count = colors.push("black"); //推入另一項(xiàng)
alert(count); //3
let item = colors.shift(); //取得第一項(xiàng)
alert(item); //"red"
alert(colors.length); //2

同時(shí)使用unshift()和pop()方法,可以從相反的方向來模擬隊(duì)列,即在數(shù)組的前端添加項(xiàng),從數(shù)組末端移除項(xiàng)。

let colors = new Array(); //創(chuàng)建一個(gè)數(shù)組
let count = colors.unshift("red", "green"); //推入兩項(xiàng)
alert(count); //2
count = colors.unshift("black"); //推入另一項(xiàng)
alert(count); //3
elt item = colors.pop(); //取得最后一項(xiàng)
alert(item); //"green"
alert(colors.length); //2

tips:IE7 及更早版本對(duì)JavaScript 的實(shí)現(xiàn)中存在一個(gè)偏差,其unshift()方法總是返回undefined 而不是數(shù)組的新長(zhǎng)度。IE8 在非兼容模式下會(huì)返回正確的長(zhǎng)度值。

2.5 重排序方法

數(shù)組中已經(jīng)存在兩個(gè)可以直接用來重排序的方法:reverse()和sort()。

let values = [1, 2, 3, 4, 5];
values.reverse();
alert(values); //5,4,3,2,1

let values = [0, 1, 5, 10, 15];
values.sort();
alert(values); //0,1,10,15,5

對(duì)于數(shù)值類型或者其valueOf()方法會(huì)返回?cái)?shù)值類型的對(duì)象類型,可以使用一個(gè)更簡(jiǎn)單的比較函數(shù)。這個(gè)函數(shù)只要用第二個(gè)值減第一個(gè)值即可。

let arr = [1,5,6,8,3,6,9];
function compare(value1, value2){
    return value2 - value1;
};
alert(arr.sort(compare)); //[9, 8, 6, 6, 5, 3, 1]
想要實(shí)現(xiàn)從小到大排列就用value1-value2
2.6 操作方法

concat()方法可以基于當(dāng)前數(shù)組中的所有項(xiàng)創(chuàng)建一個(gè)新數(shù)組。具體來說,這個(gè)方法會(huì)先創(chuàng)建當(dāng)前數(shù)組一個(gè)副本,然后將接收到的參數(shù)添加到這個(gè)副本的末尾,最后返回新構(gòu)建的數(shù)組。在沒有給concat()方法傳遞參數(shù)的情況下,它只是復(fù)制當(dāng)前數(shù)組并返回副本。如果傳遞給concat()方法的是一或多個(gè)數(shù)組,則該方法會(huì)將這些數(shù)組中的每一項(xiàng)都添加到結(jié)果數(shù)組中。如果傳遞的值不是數(shù)組,這些值就會(huì)被簡(jiǎn)單地添加到結(jié)果數(shù)組的末尾。注意:concat()方法不會(huì)影響原始數(shù)組

let colors = ["red", "green", "blue"];
let colors2 = colors.concat("blue", ["red", "brown"]);
alert(colors); //red,green,blue
alert(colors2); //red,green,blue,blue,red,brown

下一個(gè)方法是slice(),它能夠基于當(dāng)前數(shù)組中的一或多個(gè)項(xiàng)創(chuàng)建一個(gè)新數(shù)組。slice()方法可以接受一或兩個(gè)參數(shù),即要返回項(xiàng)的起始和結(jié)束位置。在只有一個(gè)參數(shù)的情況下,slice()方法返回從該參數(shù)指定位置開始到當(dāng)前數(shù)組末尾的所有項(xiàng)。如果有兩個(gè)參數(shù),該方法返回起始和結(jié)束位置之間的項(xiàng)——但不包括結(jié)束位置的項(xiàng)。注意,slice()方法不會(huì)影響原始數(shù)組。

let colors = ["red", "green", "blue", "yellow", "purple"];
let colors2 = colors.slice(1);
let colors3 = colors.slice(1,4);
alert(colors2); //green,blue,yellow,purple
alert(colors3); //green,blue,yellow

splice()方法,這個(gè)方法恐怕要算是最強(qiáng)大的數(shù)組方法了,它有很多種用法。
splice()的主要用途是向數(shù)組的中部插入項(xiàng),但使用這種方法的方式則有如下3 種。

  • 刪除:可以刪除任意數(shù)量的項(xiàng),只需指定2 個(gè)參數(shù):要?jiǎng)h除的第一項(xiàng)的位置和要?jiǎng)h除的項(xiàng)數(shù)。
    例如,splice(0,2)會(huì)刪除數(shù)組中的前兩項(xiàng)。
  • 插入:可以向指定位置插入任意數(shù)量的項(xiàng),只需提供3 個(gè)參數(shù):起始位置、0(要?jiǎng)h除的項(xiàng)數(shù))和要插入的項(xiàng)。如果要插入多個(gè)項(xiàng),可以再傳入第四、第五,以至任意多個(gè)項(xiàng)。
    例如,splice(2,0,"red","green")會(huì)從當(dāng)前數(shù)組的位置2 開始插入字符串"red"和"green"。
  • 替換:可以向指定位置插入任意數(shù)量的項(xiàng),且同時(shí)刪除任意數(shù)量的項(xiàng),只需指定3 個(gè)參數(shù):起始位置、要?jiǎng)h除的項(xiàng)數(shù)和要插入的任意數(shù)量的項(xiàng)。插入的項(xiàng)數(shù)不必與刪除的項(xiàng)數(shù)相等。
    例如,splice (2,1,"red","green")會(huì)刪除當(dāng)前數(shù)組位置2 的項(xiàng),然后再?gòu)奈恢? 開始插入字符串"red"和"green"。
    splice()方法始終都會(huì)返回一個(gè)數(shù)組,該數(shù)組中包含從原始數(shù)組中刪除的項(xiàng)(如果沒有刪除任何項(xiàng),則返回一個(gè)空數(shù)組)而且修改的其實(shí)就是原數(shù)組,所以會(huì)影響原數(shù)組。
let colors = ["red", "green", "blue"];
let removed = colors.splice(0,1); // 刪除第一項(xiàng)
alert(colors); // green,blue
alert(removed); // red,返回的數(shù)組中只包含一項(xiàng)
removed = colors.splice(1, 0, "yellow", "orange"); // 從位置1 開始插入兩項(xiàng)
alert(colors); // green,yellow,orange,blue
alert(removed); // 返回的是一個(gè)空數(shù)組
removed = colors.splice(1, 1, "red", "purple"); // 插入兩項(xiàng),刪除一項(xiàng)
alert(colors); // green,red,purple,orange,blue
alert(removed); // yellow,返回的數(shù)組中只包含一項(xiàng)
2.7 位置方法

indexOf()和lastIndexOf()。這兩個(gè)方法都接收兩個(gè)參數(shù):要查找的項(xiàng)和(可選的)表示查找起點(diǎn)位置的索引。其中,indexOf()方法從數(shù)組的開頭(位置0)開始向后查找,lastIndexOf()方法則從數(shù)組的末尾開始向前查找。
這兩個(gè)方法都返回要查找的項(xiàng)在數(shù)組中的位置,或者在沒找到的情況下返回-1。在比較第一個(gè)參數(shù)與數(shù)組中的每一項(xiàng)時(shí),會(huì)使用全等操作符;也就是說,要求查找的項(xiàng)必須嚴(yán)格相等(就像使用===一樣)。

let numbers = [1,2,3,4,5,4,3,2,1];
alert(numbers.indexOf(4)); //3
alert(numbers.lastIndexOf(4)); //5
alert(numbers.indexOf(4, 4)); //5
alert(numbers.lastIndexOf(4, 4)); //3
var person = { name: "Nicholas" };
var people = [{ name: "Nicholas" }];
var morePeople = [person];
alert(people.indexOf(person)); //-1
alert(morePeople.indexOf(person)); //0

使用indexOf()和lastIndexOf()方法查找特定項(xiàng)在數(shù)組中的位置非常簡(jiǎn)單,支持它們的瀏覽器包括IE9+、Firefox 2+、Safari 3+、Opera 9.5+和Chrome。

2.8 迭代方法

數(shù)組定義了5 個(gè)迭代方法。每個(gè)方法都接收兩個(gè)參數(shù):要在每一項(xiàng)上運(yùn)行的函數(shù)和(可選的)運(yùn)行該函數(shù)的作用域?qū)ο蟆绊憈his 的值。傳入這些方法中的函數(shù)會(huì)接收三個(gè)參數(shù):數(shù)組項(xiàng)的值、該項(xiàng)在數(shù)組中的位置和數(shù)組對(duì)象本身。根據(jù)使用的方法不同,這個(gè)函數(shù)執(zhí)行后的返回值可能會(huì)也可能不會(huì)影響方法的返回值。

  • every():對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù),如果該函數(shù)對(duì)每一項(xiàng)都返回true,則返回true。
  • filter():對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù),返回該函數(shù)會(huì)返回true 的項(xiàng)組成的數(shù)組。
  • forEach():對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù)。這個(gè)方法沒有返回值。
  • map():對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù),返回每次函數(shù)調(diào)用的結(jié)果組成的數(shù)組。
  • some():對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù),如果該函數(shù)對(duì)任一項(xiàng)返回true,則返回true。

以上方法都不會(huì)修改數(shù)組中的包含的值。
在這些方法中,最相似的是every()和some(),它們都用于查詢數(shù)組中的項(xiàng)是否滿足某個(gè)條件。對(duì)every()來說,傳入的函數(shù)必須對(duì)每一項(xiàng)都返回true,這個(gè)方法才返回true;否則,它就返回false。而some()方法則是只要傳入的函數(shù)對(duì)數(shù)組中的某一項(xiàng)返回true,就會(huì)返回true。

  • 最后一個(gè)方法是forEach(),它只是對(duì)數(shù)組中的每一項(xiàng)運(yùn)行傳入的函數(shù)。這個(gè)方法沒有返回值,本質(zhì)上與使用for 循環(huán)迭代數(shù)組一樣。
let numbers = [1,2,3,4,5,4,3,2,1];
numbers.forEach(function(item, index, array){
    //執(zhí)行某些操作
});

這些數(shù)組方法通過執(zhí)行不同的操作,可以大大方便處理數(shù)組的任務(wù)。支持這些迭代方法的瀏覽器有IE9+、Firefox 2+、Safari 3+、Opera 9.5+和Chrome。

2.9 歸并方法

ECMAScript 5 還新增了兩個(gè)歸并數(shù)組的方法:reduce()和reduceRight()。這兩個(gè)方法都會(huì)迭代數(shù)組的所有項(xiàng),然后構(gòu)建一個(gè)最終返回的值。其中,reduce()方法從數(shù)組的第一項(xiàng)開始,逐個(gè)遍歷到最后。而reduceRight()則從數(shù)組的最后一項(xiàng)開始,向前遍歷到第一項(xiàng)。
這兩個(gè)方法都接收兩個(gè)參數(shù):一個(gè)在每一項(xiàng)上調(diào)用的函數(shù)和(可選的)作為歸并基礎(chǔ)的初始值。傳給reduce()和reduceRight()的函數(shù)接收4 個(gè)參數(shù):前一個(gè)值、當(dāng)前值、項(xiàng)的索引和數(shù)組對(duì)象。這個(gè)函數(shù)返回的任何值都會(huì)作為第一個(gè)參數(shù)自動(dòng)傳給下一項(xiàng)。第一次迭代發(fā)生在數(shù)組的第二項(xiàng)上,因此第一個(gè)參數(shù)是數(shù)組的第一項(xiàng),第二個(gè)參數(shù)就是數(shù)組的第二項(xiàng)

使用reduce()方法可以執(zhí)行求數(shù)組中所有值之和的操作,比如:

let values = [1,2,3,4,5];
let sum = values.reduce(function(prev, cur, index, array){
return prev + cur;
});
alert(sum); //15

第一次執(zhí)行回調(diào)函數(shù),prev 是1,cur 是2。第二次,prev 是3(1 加2 的結(jié)果),cur 是3(數(shù)組的第三項(xiàng))。這個(gè)過程會(huì)持續(xù)到把數(shù)組中的每一項(xiàng)都訪問一遍,最后返回結(jié)果。reduceRight()的作用類似,只不過方向相反而已。
支持這兩個(gè)歸并函數(shù)的瀏覽器有IE9+、Firefox 3+、Safari 4+、Opera 10.5 和Chrome。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容