成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

《JavaScript 闖關(guān)記》之?dāng)?shù)組

daryl / 2067人閱讀

摘要:針對(duì)非稀疏數(shù)組,該屬性就是數(shù)組元素的個(gè)數(shù)。否則,使用數(shù)組元素之前應(yīng)該先檢測它們。如果數(shù)組同時(shí)擁有對(duì)象屬性和數(shù)組元素,返回的屬性名很可能是按照創(chuàng)建的順序而非數(shù)值的大小順序。并且,每個(gè)全局對(duì)象有自己的一組構(gòu)造函數(shù)。

數(shù)組是值的有序集合。每個(gè)值叫做一個(gè)元素,而每個(gè)元素在數(shù)組中有一個(gè)位置,以數(shù)字表示,稱為索引。

JavaScript 數(shù)組是無類型的,數(shù)組元素可以是任意類型,并且同一個(gè)數(shù)組中的不同元素也可能有不同的類型。數(shù)組的元素甚至也可能是對(duì)象或其他數(shù)組。

JavaScript數(shù)組是動(dòng)態(tài)的,根據(jù)需要它們會(huì)增長或縮減,并且在創(chuàng)建數(shù)組時(shí)無須聲明一個(gè)固定的大小或者在數(shù)組大小變化時(shí)無須重新分配空間。

JavaScript 數(shù)組可能是稀疏的,數(shù)組元素的索引不一定要連續(xù)的,它們之間可以有空缺。每個(gè)JavaScript數(shù)組都有一個(gè)length屬性。針對(duì)非稀疏數(shù)組,該屬性就是數(shù)組元素的個(gè)數(shù)。針對(duì)稀疏數(shù)組,length比所有元素的索引要大。

JavaScript 數(shù)組是 JavaScript 對(duì)象的特殊形式,數(shù)組索引實(shí)際上和碰巧是整數(shù)的屬性名差不多。通常,數(shù)組的實(shí)現(xiàn)是經(jīng)過優(yōu)化的,用數(shù)字索引來訪問數(shù)組元素一般來說比訪問常規(guī)的對(duì)象屬性要快很多。

數(shù)組繼承自 Array.prototype 中的屬性,它定義了一套豐富的數(shù)組操作方法。

創(chuàng)建數(shù)組

可以使用數(shù)組字面量和 new 關(guān)鍵字來創(chuàng)建數(shù)組。

使用數(shù)組字面量創(chuàng)建數(shù)組(推薦)
var empty = [];                 // 沒有元素的數(shù)組
var primes = [2, 3, 5, 7, 11];  // 有5個(gè)數(shù)值的數(shù)組
var misc = [1.1, true, "a"];    // 3個(gè)不同類型的元素

// 數(shù)組直接量中的值不一定要是常量,可以是任意的表達(dá)式
var base = 1024;
var table = [base, base+1, base+2, base+3];

// 也可以包含對(duì)象直接量或其他數(shù)組直接量
var b = [[1, {x:1, y:2}], [2, {x:3, y:4}]];

注意,不要忽略數(shù)組字面量的最后一個(gè)元素,僅以逗號(hào)結(jié)尾。下面幾個(gè)案例,在不同的瀏覽器下,可能會(huì)被識(shí)別成2個(gè)元素,也有可能識(shí)別成3個(gè)元素,而造成程序bug。例如:

var nums = [,,,];               // 不好的寫法
var names = ["stone",,];        // 不好的寫法
var colors = ["red","green",];  // 不好的寫法
使用 new 關(guān)鍵字創(chuàng)建數(shù)組

使用 new 關(guān)鍵字調(diào)用構(gòu)造函數(shù) Array() 是創(chuàng)建數(shù)組的另一種方法,可以用三種方式調(diào)用構(gòu)造函數(shù)。例如:

// 調(diào)用時(shí)沒有參數(shù)
var a = new Array();

// 調(diào)用時(shí)有一個(gè)數(shù)值參數(shù),它指定長度
var a = new Array(10); 

// 顯式指定多個(gè)數(shù)組元素或者數(shù)組的一個(gè)非數(shù)值元素
var a = new Array(5, 4, 3, 2, 1, "testing");
數(shù)組元素的讀和寫

使用 [] 操作符來訪問數(shù)組中的一個(gè)元素。數(shù)組的引用位于方括號(hào)的左邊。方括號(hào)中是一個(gè)返回非負(fù)整數(shù)值的任意表達(dá)式。使用該語法既可以讀又可以寫數(shù)組的一個(gè)元素。例如:

var a = ["world"];     // 從一個(gè)元素的數(shù)組開始
var value = a[0];      // 讀第0個(gè)元素
a[1] = 3.14;           // 寫第1個(gè)元素
var i = 2; 
a[i] = 3;              // 寫第2個(gè)元素
a[i + 1] = "hello";    // 寫第3個(gè)元素
a[a[i]] = a[0];        // 讀第0個(gè)和第2個(gè)元素,寫第3個(gè)元素

請(qǐng)記住,數(shù)組是對(duì)象的特殊形式,可以為其創(chuàng)建任意名字的屬性。但如果使用的屬性是數(shù)組的索引,數(shù)組的特殊行為就是將根據(jù)需要更新它們的length屬性值。

注意,可以使用負(fù)數(shù)或非整數(shù)來索引數(shù)組。這種情況下,數(shù)值轉(zhuǎn)換為字符串,字符串作為屬性名來用。既然名字不是非負(fù)整數(shù),它就只能當(dāng)做常規(guī)的對(duì)象屬性,而非數(shù)組的索引。同樣,如果湊巧使用了是非負(fù)整數(shù)的字符串,它就當(dāng)做數(shù)組索引,而非對(duì)象屬性。當(dāng)使用的一個(gè)浮點(diǎn)數(shù)和一個(gè)整數(shù)相等時(shí)情況也是一樣的。例如:

a[-1.23] = true;  // 這將創(chuàng)建一個(gè)名為"-1.23"的屬性
a["1000"] = 0;    // 這是數(shù)組的第1001個(gè)元素
a[1.000]          // 和 a[1] 相等

事實(shí)上數(shù)組索引僅僅是對(duì)象屬性名的一種特殊類型,這意味著 JavaScript 數(shù)組沒有「越界」錯(cuò)誤的概念。當(dāng)試圖查詢?nèi)魏螌?duì)象中不存在的屬性時(shí),不會(huì)報(bào)錯(cuò),只會(huì)得到 undefined 值。

稀疏數(shù)組

稀疏數(shù)組就是包含從0開始的不連續(xù)索引的數(shù)組。通常,數(shù)組的 length 屬性值代表數(shù)組中元素的個(gè)數(shù)。如果數(shù)組是稀疏的,length 屬性值大于元素的個(gè)數(shù)。可以用 Array() 構(gòu)造函數(shù)或簡單地指定數(shù)組的索引值大于當(dāng)前的數(shù)組長度來創(chuàng)建稀疏數(shù)組。

a = new Array(5);   // 數(shù)組沒有元素,但是 a.length = 5
a = [];             // 創(chuàng)建一個(gè)空數(shù)組,a.length = 0
a[1000] = 0;        // 添加一個(gè)元素,a.length 被自動(dòng)更新為1001

足夠稀疏的數(shù)組通常在實(shí)現(xiàn)上比稠密的數(shù)組更慢、內(nèi)存利用率更高,在這樣的數(shù)組中查找元素的時(shí)間與常規(guī)對(duì)象屬性的查找時(shí)間一樣長。

需要注意的是,當(dāng)省略數(shù)組直接量中的值時(shí)(使用連續(xù)的逗號(hào),比如 [1,,3] ),這時(shí)所得到的數(shù)組也是稀疏數(shù)組,省略掉的值是不存在的:

var a1 = [,"1","2"];    // 此數(shù)組長度是3 
var a2 = [undefined];   // 此數(shù)組包含一個(gè)值為 undefined 的元素 
console.log(0 in a1);   // false,a1 在索引0處沒有元素
console.log(0 in a2);   // true,a2 在索引0處有一個(gè)值為 undefined 的元素 

了解稀疏數(shù)組是了解 JavaScript 數(shù)組的真實(shí)本質(zhì)的一部分。盡管如此,實(shí)際上你所碰到的絕大多數(shù) JavaScript 數(shù)組不是稀疏數(shù)組。并且,如果你確實(shí)碰到了稀疏數(shù)組,你的代碼很可能像對(duì)待非稀疏數(shù)組一樣來對(duì)待它們,只不過它們包含一些 undefined 值。

數(shù)組長度

每個(gè)數(shù)組有一個(gè) length 屬性,就是這個(gè)屬性使其區(qū)別于常規(guī)的 JavaScript 對(duì)象。針對(duì)稠密(也就是非稀疏)數(shù)組,length 屬性值代表數(shù)組中元素的個(gè)數(shù)。其值比數(shù)組中最大的索引大1。例如:

[].length             // 0,數(shù)組沒有元素
["a","b","c"].length  // 3,最大的索引為2,length 為3

當(dāng)數(shù)組是稀疏的時(shí),length 屬性值大于元素的個(gè)數(shù)。而且關(guān)于此我們可以說的一切也就是數(shù)組長度保證大于它每個(gè)元素的索引值?;蛘?,換一種說法,在數(shù)組中(無論稀疏與否)肯定找不到一個(gè)元素的索引值大于或等于它的長度。為了維持此規(guī)則不變化,數(shù)組有兩個(gè)特殊的行為。

第一個(gè)如同上面的描述:如果為一個(gè)數(shù)組元素賦值,它的索引 i 大于或等于現(xiàn)有數(shù)組的長度時(shí),length 屬性的值將設(shè)置為 i+1

第二個(gè)特殊的行為就是設(shè)置 length 屬性為一個(gè)小于當(dāng)前長度的非負(fù)整數(shù) n 時(shí),當(dāng)前數(shù)組中那些索引值大于或等于 n 的元素將從中刪除。例如:

a = [1,2,3,4,5];     // 從5個(gè)元素的數(shù)組開始
a.length = 3;        // 現(xiàn)在 a 為[1,2,3]
a.length = 0;        // 刪除所有的元素。a 為[ ]
a.length = 5;        // 長度為5,但是沒有元素,就像 new Array(5)

還可以將數(shù)組的 length 屬性值設(shè)置為大于其當(dāng)前的長度。實(shí)際上這不會(huì)向數(shù)組中添加新的元素,它只是在數(shù)組尾部創(chuàng)建一個(gè)空的區(qū)域。

在 ECMAScript 5中,可以用 Object.defineProperty() 讓數(shù)組的 length 屬性變成只讀的。例如:

a = [1,2,3];                                            // 從3個(gè)元素的數(shù)組開始
Object.defineProperty(a, "length", {writable: false});  // 讓 length 屬性只讀
a.length = 0;                                           // a 不會(huì)改變
數(shù)組元素的添加和刪除

我們已經(jīng)見過添加數(shù)組元素最簡單的方法,為新索引賦值。例如:

a = []           // 開始是一個(gè)空數(shù)組
a[0] = "zero";   // 然后向其中添加元素
a[1] = "one";

也可以使用 push() 方法在數(shù)組末尾增加一個(gè)或多個(gè)元素。例如:

a = [];                 // 開始是一個(gè)空數(shù)組
a.push("zero");         // 在末尾添加一個(gè)元素。a = ["zero"]
a.push("one", "two");   // 再添加兩個(gè)元素。a = ["zero", "one", "two"]

可以像刪除對(duì)象屬性一樣使用 delete 運(yùn)算符來刪除數(shù)組元素。例如:

a = [1,2,3]; 
delete a[1];   // a在索引1的位置不再有元素
1 in a         // => false: 數(shù)組索引1并未在數(shù)組中定義
a.length       // => 3: delete操作并不影響數(shù)組長度

注意,對(duì)一個(gè)數(shù)組元素使用 delete 不會(huì)修改數(shù)組的 length 屬性,也不會(huì)將元素從高索引處移下來填充已刪除屬性留下的空白。如果從數(shù)組中刪除一個(gè)元素,它就變成稀疏數(shù)組。

數(shù)組遍歷

使用 for 循環(huán)是遍歷數(shù)組元素最常見的方法。例如:

var keys = Object.keys(o);   // 獲得 o 對(duì)象屬性名組成的數(shù)組
var values = []              // 在數(shù)組中存儲(chǔ)匹配屬性的值
for(var i = 0; i < keys.length; i++) {  // 對(duì)于數(shù)組中每個(gè)索引
    var key = keys[i];                  // 獲得索引處的鍵值
    values[i] = o[key];                 // 在 values 數(shù)組中保存屬性值
}

在嵌套循環(huán)或其他性能非常重要的上下文中,可以看到這種基本的數(shù)組遍歷需要優(yōu)化,數(shù)組的長度應(yīng)該只查詢一次而非每次循環(huán)都要查詢。例如:

for(var i = 0, len = keys.length; i < len; i++) {
   // 循環(huán)體仍然不變
}

這些例子假設(shè)數(shù)組是稠密的,并且所有的元素都是合法數(shù)據(jù)。否則,使用數(shù)組元素之前應(yīng)該先檢測它們。例如:

for(var i = 0; i < a.length; i++) {
    if (!a[i]) continue;    // 跳過 null、undefined 和不存在的元素
    if (!(i in a)) continue ;   // 跳過不存在的元素
    if (a[i] === undefined) continue;   // 跳過 undefined 和不存在的元素
    // 循環(huán)體
}

還可以使用 for-in 循環(huán)處理稀疏數(shù)組。循環(huán)每次將一個(gè)可枚舉的屬性名(包括數(shù)組索引)賦值給循環(huán)變量,不存在的索引將不會(huì)遍歷到。例如:

for(var index in sparseArray) {
   var value = sparseArray[index];
   // 此處可以使用索引和值做一些事情
}

但由于 for-in 循環(huán)能夠枚舉繼承的屬性名,如添加到 Array.prototype 中的方法。基于這個(gè)原因,在數(shù)組上不應(yīng)該使用 for-in 循環(huán),除非使用額外的檢測方法來過濾不想要的屬性。例如:

for(var i in a) {
    // 跳過繼承的屬性
    if (!a.hasOwnProperty(i)) continue;

    // 跳過不是非負(fù)整數(shù)的 i
    if (String(Math.floor(Math.abs(Number(i)))) !== i) continue;
}

JavaScript 規(guī)范允許 for-in 循環(huán)以不同的順序遍歷對(duì)象的屬性。通常數(shù)組元素的遍歷實(shí)現(xiàn)是升序的,但不能保證一定是這樣的。如果數(shù)組同時(shí)擁有對(duì)象屬性和數(shù)組元素,返回的屬性名很可能是按照創(chuàng)建的順序而非數(shù)值的大小順序。如何處理這個(gè)問題的實(shí)現(xiàn),各個(gè)瀏覽器都不相同,如果算法依賴于遍歷的順序,那么最好不要使用 for-in 而用常規(guī)的 for 循環(huán)。

ECMAScript 5定義了一些遍歷數(shù)組元素的新方法,按照索引的順序按個(gè)傳遞給定義的一個(gè)函數(shù)。這些方法中最常用的就是 forEach() 方法。例如:

var data = [1,2,3,4,5];     // 這是需要遍歷的數(shù)組
var sumOfSquares = 0;       // 要得到數(shù)據(jù)的平方和
data.forEach(function(x) {  // 把每個(gè)元素傳遞給此函數(shù)
    sumOfSquares += x*x;    // 平方相加
});
console.log(sumOfSquares);  // 55,1 + 4 + 9 + 16 + 25
數(shù)組檢測

給定一個(gè)未知的對(duì)象,判定它是否為數(shù)組通常非常有用。在 ECMAScript 5中,可以使用 Array.isArray() 函數(shù)來做這件事情。例如:

Array.isArray([])   // true
Array.isArray({})   // false

但是,在 ECMAScript 5以前,要區(qū)分?jǐn)?shù)組和非數(shù)組對(duì)象很困難。typeof 運(yùn)算符對(duì)數(shù)組返回 "object"(并且對(duì)于除了函數(shù)以外的所有對(duì)象都是如此)。instanceof 操作符也只能用于簡單的情形。例如:

[] instanceof Array     // true
({}) instanceof Array   // false

使用 instanceof 的問題是在 Web 瀏覽器中有可能有多個(gè)窗體存在。每個(gè)窗體都有自己的 JavaScript 環(huán)境,有自己的全局對(duì)象。并且,每個(gè)全局對(duì)象有自己的一組構(gòu)造函數(shù)。因此一個(gè)窗體中的對(duì)象將不可能是另外窗體中的構(gòu)造函數(shù)的實(shí)例。窗體之間的混淆不常發(fā)生,但這個(gè)問題足已證明 instanceof 操作符不能視為一個(gè)可靠的數(shù)組檢測方法。

解決方案是檢查對(duì)象的類屬性,對(duì)數(shù)組而言該屬性的值總是 "Array",因此在 ECMAScript 3中 isArray() 函數(shù)的代碼可以這樣書寫。例如:

var isArray = Array.isArray || function(o) {
    return typeof o === "object" && Object.prototype.toString.call(o) === "[object Array]";
};
數(shù)組方法

ECMAScript 3和 ECMAScript 5在 Array.prototype 中定義了一些很有用的操作數(shù)組的方法。

轉(zhuǎn)換方法

所有對(duì)象都具有 toLocaleString()、toString()valueOf() 方法。其中,調(diào)用數(shù)組的 toString()valueOf() 方法會(huì)返回相同的值,即由數(shù)組中每個(gè)值的字符串形式拼接而成的一個(gè)以逗號(hào)分隔的字符串。實(shí)際上,為了創(chuàng)建這個(gè)字符串會(huì)調(diào)用數(shù)組每一項(xiàng)的 toString() 方法。例如:

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

在這里,我們首先顯式地調(diào)用了 toString()valueOf() 方法,以便返回?cái)?shù)組的字符串表示,每個(gè)值的字符串表示拼接成了一個(gè)字符串,中間以逗號(hào)分隔。最后一行代碼直接將數(shù)組傳遞給了 alert()。由于 alert()要接收字符串參數(shù),所以它會(huì)在后臺(tái)調(diào)用 toString() 方法,由此會(huì)得到與直接調(diào)用 toString() 方法相同的結(jié)果。

另外,toLocaleString() 方法經(jīng)常也會(huì)返回與 toString()valueOf() 方法相同的值,但也不總是如此。當(dāng)調(diào)用數(shù)組的 toLocaleString() 方法時(shí),它也會(huì)創(chuàng)建一個(gè)數(shù)組值的以逗號(hào)分隔的字符串。而與前兩個(gè)方法唯一的不同之處在于,這一次為了取得每一項(xiàng)的值,調(diào)用的是每一項(xiàng)的 toLocaleString() 方法,而不是 toString() 方法。例如:

var person1 = {
    toLocaleString : function () {
        return "Nikolaos";
    },
    toString : function() {
        return "Nicholas";
    }
};

var person2 = {
    toLocaleString : function () {
        return "Grigorios";
    },
    toString : function() {
        return "Greg";
    }
};

var people = [person1, person2];
alert(people);                           // Nicholas,Greg
alert(people.toString());                // Nicholas,Greg
alert(people.toLocaleString());          // Nikolaos,Grigorios

數(shù)組繼承的 toLocaleString()、toString()valueOf()方法,在默認(rèn)情況下都會(huì)以逗號(hào)分隔的字符串的形式返回?cái)?shù)組項(xiàng)。而如果使用 join() 方法,則可以使用不同的分隔符來構(gòu)建這個(gè)字符串。join() 方法只接收一個(gè)參數(shù),即用作分隔符的字符串,然后返回包含所有數(shù)組項(xiàng)的字符串。例如:

var colors = ["red", "green", "blue"];
console.log(colors.join(","));    // red,green,blue
console.log(colors.join("||"));   // red||green||blue

如果數(shù)組中的某一項(xiàng)的值是 null 或者 undefined,那么該值在 join()、toLocaleString()、toString()valueOf() 方法返回的結(jié)果中以空字符串表示。

棧方法

棧是一種 LIFO(Last-In-First-Out,后進(jìn)先出)的數(shù)據(jù)結(jié)構(gòu),也就是最新添加的項(xiàng)最早被移除。push() 方法可以接收任意數(shù)量的參數(shù),把它們逐個(gè)添加到數(shù)組末尾,并返回修改后數(shù)組的長度。而 pop() 方法則從數(shù)組末尾移除最后一項(xiàng),減少數(shù)組的 length 值,然后返回移除的項(xiàng)。結(jié)合 push()pop() 方法,就可以像棧一樣使用數(shù)組。例如:

var colors = [];                            // 創(chuàng)建一個(gè)數(shù)組
var count = colors.push("red", "green");    // 推入兩項(xiàng)
console.log(count);                         // 2,數(shù)組的長度

count = colors.push("black");               // 推入另一項(xiàng)
console.log(count);                         // 3,數(shù)組的長度

var item = colors.pop();                    // 取得最后一項(xiàng)
console.log(item);                          // "black"
console.log(colors.length);                 // 2,數(shù)組的長度
隊(duì)列方法

隊(duì)列是一種 FIFO(First-In-First-Out,先進(jìn)先出)的數(shù)據(jù)結(jié)構(gòu),隊(duì)列在列表的末端添加項(xiàng),從列表的前端移除項(xiàng)。shift() 方法則從數(shù)組前端移除第一項(xiàng),減少數(shù)組的 length 值,然后返回移除的項(xiàng)。結(jié)合 push()shift() 方法,就可以像隊(duì)列一樣使用數(shù)組。例如:

var colors = [];                            // 創(chuàng)建一個(gè)數(shù)組
var count = colors.push("red", "green");    // 推入兩項(xiàng)
console.log(count);                         // 2,數(shù)組的長度

count = colors.push("black");               // 推入另一項(xiàng)
console.log(count);                         // 3,數(shù)組的長度

var item = colors.shift();                  // 取得第一項(xiàng)
console.log(item);                          // "red"
console.log(colors.length);                 // 2,數(shù)組的長度

JavaScipt 還為數(shù)組提供了一個(gè) unshift() 方法。顧名思義,unshift()shift() 的用途相反,它能在數(shù)組前端添加任意個(gè)項(xiàng)并返回新數(shù)組的長度。因此,同時(shí)使用 unshift()pop() 方法,可以從相反的方向來模擬隊(duì)列,即在數(shù)組的前端添加項(xiàng),從數(shù)組末端移除項(xiàng)。

重排序方法

數(shù)組中有兩個(gè)重排序的方法:reverse()sort()。reverse() 方法可以反轉(zhuǎn)數(shù)組元素的順序。例如:

var values = [1, 2, 3, 4, 5];
values.reverse();
console.log(values);  // 5,4,3,2,1

sort() 方法可以按升序排列數(shù)組元素(即最小的值位于最前面,最大的值排在最后面)。sort() 方法在排序的過程中會(huì)調(diào)用每個(gè)數(shù)組元素的 toString(),然后比較得到的字符串,以確定如何排序。即使數(shù)組中的每一項(xiàng)都是數(shù)值,sort() 方法比較的也是字符串,例如:

var values = [0, 1, 5, 10, 15];
values.sort();
console.log(values);     // 0,1,10,15,5

這種排序方式在很多情況下都不是最佳方案,因此 sort() 方法可以接收一個(gè)比較函數(shù)作為參數(shù),以便我們指定哪個(gè)值位于哪個(gè)值的前面,以下就是一個(gè)簡單的比較函數(shù)。例如:

function compare(value1, value2) {
    if (value1 < value2) {
        return -1;
    } else if (value1 > value2) {
        return 1;
    } else {
        return 0;
    }
}

這個(gè)比較函數(shù)接收兩個(gè)參數(shù),如果第一個(gè)參數(shù)應(yīng)該位于第二個(gè)之前則返回一個(gè)負(fù)數(shù),如果兩個(gè)參數(shù)相等則返回0,如果第一個(gè)參數(shù)應(yīng)該位于第二個(gè)之后則返回一個(gè)正數(shù)。它可以適用于大多數(shù)情況,只要將其作為參數(shù)傳遞給 sort() 方法即可。例如:

var values = [10, 5, 1, 0, 15];
values.sort(compare);
console.log(values);   // 0,1,5,10,15

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

function compare(value1, value2){
    return value2 - value1;
}

由于比較函數(shù)通過返回一個(gè)小于零、等于零或大于零的值來影響排序結(jié)果,因此減法操作就可以適當(dāng)?shù)靥幚硭羞@些情況。

操作方法

JavaScript 為操作已經(jīng)包含在數(shù)組中的元素提供了很多方法。其中,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é)果數(shù)組的末尾。例如:

var colors = ["red", "green", "blue"];
var colors2 = colors.concat("yellow", ["black", "brown"]);

console.log(colors);     // red,green,blue
console.log(colors2);    // red,green,blue,yellow,black,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ù)組。例如:

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

console.log(colors2);   // green,blue,yellow,purple
console.log(colors3);   // green,blue,yellow

如果 slice() 方法的參數(shù)中有一個(gè)負(fù)數(shù),則用數(shù)組長度加上該數(shù)來確定相應(yīng)的位置。例如,在一個(gè)包含5項(xiàng)的數(shù)組上調(diào)用 slice(-2,-1) 與調(diào)用 slice(3,4) 得到的結(jié)果相同。如果結(jié)束位置小于起始位置,則返回空數(shù)組。

下一個(gè)方法是 splice(),它的主要用途是向數(shù)組的中部插入元素,主要有以下3種使用方式。

刪除:可以刪除任意數(shù)量的項(xiàng),只需指定2個(gè)參數(shù):起始位置和要?jiǎng)h除元素的數(shù)量。例如,splice(0,2) 會(huì)刪除數(shù)組中的前兩項(xiàng)。

插入:可以向指定位置插入任意數(shù)量的項(xiàng),只需提供3個(gè)參數(shù):起始位置、0(要?jiǎng)h除元素的數(shù)量)和要插入的元素。如果要插入多個(gè)元素,可以再傳入第四、第五,以至任意多個(gè)元素。例如,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除元素的數(shù)量和要插入的元素。插入的項(xiàng)數(shù)不必與刪除的項(xiàng)數(shù)相等。例如,splice (2,1,"red","green")會(huì)刪除當(dāng)前數(shù)組位置2的項(xiàng),然后再從位置2開始插入字符串 "red""green"

splice() 方法始終都會(huì)返回一個(gè)數(shù)組,該數(shù)組中包含從原始數(shù)組中刪除的項(xiàng)(如果沒有刪除任何項(xiàng),則返回一個(gè)空數(shù)組)。下面的代碼展示了上述3種使用 splice() 方法的方式。例如:

var colors = ["red", "green", "blue"];
var removed = colors.splice(0,1);       // 刪除第一項(xiàng)
console.log(colors);                    // green,blue
console.log(removed);                   // red,返回的數(shù)組中只包含一項(xiàng)

removed = colors.splice(1, 0, "yellow", "orange");  // 從位置1開始插入兩項(xiàng)
console.log(colors);                    // green,yellow,orange,blue
console.log(removed);                   // 返回的是一個(gè)空數(shù)組

removed = colors.splice(1, 1, "red", "purple");     // 插入兩項(xiàng),刪除一項(xiàng)
console.log(colors);                    // green,red,purple,orange,blue
console.log(removed);                   // yellow,返回的數(shù)組中只包含一項(xiàng)
位置方法

ECMAScript 5為數(shù)組實(shí)例添加了兩個(gè)位置方法: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)格相等(就像使用 === 一樣)。例如:

var numbers = [1,2,3,4,5,4,3,2,1];
console.log(numbers.indexOf(4));          // 3
console.log(numbers.lastIndexOf(4));      // 5
console.log(numbers.indexOf(4, 4));       // 5
console.log(numbers.lastIndexOf(4, 4));   // 3

var person = { name: "Nicholas" };
var people = [{ name: "Nicholas" }];
var morePeople = [person];
console.log(people.indexOf(person));      // -1
console.log(morePeople.indexOf(person));  // 0
迭代方法

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

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。例如:

var numbers = [1,2,3,4,5,4,3,2,1];
var everyResult = numbers.every(function(item, index, array){
    return (item > 2); 
});
console.log(everyResult);   // false

var someResult = numbers.some(function(item, index, array){
    return (item > 2);
});
console.log(someResult);    // true

下面再看一看 filter() 函數(shù),它利用指定的函數(shù)確定是否在返回的數(shù)組中包含的某一項(xiàng)。例如:

var numbers = [1,2,3,4,5,4,3,2,1];
var filterResult = numbers.filter(function(item, index, array){
    return (item > 2);
});
console.log(filterResult);  // [3,4,5,4,3]

map() 也返回一個(gè)數(shù)組,而這個(gè)數(shù)組的每一項(xiàng)都是在原始數(shù)組中的對(duì)應(yīng)項(xiàng)上運(yùn)行傳入函數(shù)的結(jié)果。例如,可以給數(shù)組中的每一項(xiàng)乘以2,然后返回這些乘積組成的數(shù)組。例如:

var numbers = [1,2,3,4,5,4,3,2,1];
var mapResult = numbers.map(function(item, index, array){
    return item * 2;
});
console.log(mapResult);     // [2,4,6,8,10,8,6,4,2]

最后一個(gè)方法是 forEach(),它只是對(duì)數(shù)組中的每一項(xiàng)運(yùn)行傳入的函數(shù)。這個(gè)方法沒有返回值,本質(zhì)上與使用 for 循環(huán)迭代數(shù)組一樣。例如:

var numbers = [1,2,3,4,5,4,3,2,1];
numbers.forEach(function(item, index, array){
    //執(zhí)行某些操作 
});
 縮小方法

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ù)組中所有值之和的操作。例如:

var values = [1,2,3,4,5];
var sum = values.reduce(function(prev, cur, index, array){
    return prev + cur; 
});
console.log(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() 的作用類似,只不過方向相反而已。例如:

var values = [1,2,3,4,5];
var sum = values.reduceRight(function(prev, cur, index, array){
    return prev + cur;
});
console.log(sum); // 15

使用 reduce() 還是 reduceRight(),主要取決于要從哪頭開始遍歷數(shù)組。除此之外,它們完全相同。

關(guān)卡

完成下面3個(gè)數(shù)組去重方法。

// 挑戰(zhàn)一,一維數(shù)組
var arr = [2,3,4,2,3,5,6,4,3,2];
var unique = function(arr){
    // 待實(shí)現(xiàn)方法體
}
console.log(unique(arr)); // [2,3,4,5,6]
// 挑戰(zhàn)二,二維數(shù)組
var arr = [2,3,4,[2,3,4,5],3,5,[2,3,4,2],4,3,6,2];
var unique = function(arr){
    // 待實(shí)現(xiàn)方法體
}
console.log(unique(arr)); // [2,3,4,5,6]
// 挑戰(zhàn)三,三維數(shù)組或 n 維數(shù)組
var arr = [2,3,4,[2,3,[2,3,4,2],5],3,5,[2,3,[2,3,4,2],2],4,3,6,2];
var unique = function(arr){
    // 待實(shí)現(xiàn)方法體
}
console.log(unique(arr)); // [2,3,4,5,6]
更多

關(guān)注微信公眾號(hào)「劼哥舍」回復(fù)「答案」,獲取關(guān)卡詳解。
關(guān)注 https://github.com/stone0090/javascript-lessons,獲取最新動(dòng)態(tài)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/80609.html

相關(guān)文章

  • JavaScript 闖關(guān)

    摘要:對(duì)象數(shù)組初始化表達(dá)式,闖關(guān)記之上文檔對(duì)象模型是針對(duì)和文檔的一個(gè)。闖關(guān)記之?dāng)?shù)組數(shù)組是值的有序集合。數(shù)組是動(dòng)態(tài)的,根闖關(guān)記之語法的語法大量借鑒了及其他類語言如和的語法。 《JavaScript 闖關(guān)記》之 DOM(下) Element 類型 除了 Document 類型之外,Element 類型就要算是 Web 編程中最常用的類型了。Element 類型用于表現(xiàn) XML 或 HTML 元素...

    mj 評(píng)論0 收藏0
  • JavaScript 闖關(guān)函數(shù)

    摘要:把上面的函數(shù)聲明改為等價(jià)的函數(shù)表達(dá)式,就會(huì)在執(zhí)行期間導(dǎo)致錯(cuò)誤。換句話說,引用的是函數(shù)據(jù)以執(zhí)行的環(huán)境對(duì)象當(dāng)在網(wǎng)頁的全局作用域中調(diào)用函數(shù)時(shí),對(duì)象引用的就是。這兩個(gè)方法的用途都是在特定的作用域中調(diào)用函數(shù),實(shí)際上等于設(shè)置函數(shù)體內(nèi)對(duì)象的值。 函數(shù)是一段代碼,它只定義一次,但可以被執(zhí)行或調(diào)用任意次。在 JavaScript 里,函數(shù)即對(duì)象,程序可以隨意操控它們。比如,可以把函數(shù)賦值給變量,或者作為...

    alphahans 評(píng)論0 收藏0
  • JavaScript 闖關(guān)語法

    摘要:的語法大量借鑒了及其他類語言如和的語法。也就是說,關(guān)鍵字變量函數(shù)名和所有的標(biāo)識(shí)符都必須采取一致的大小寫形式。中的字面量有字符串?dāng)?shù)字布爾值對(duì)象數(shù)組函數(shù)正則表達(dá)式,以及特殊的值。這是為了不破壞語法而特意選定的語法。 JavaScript 的語法大量借鑒了 C 及其他類 C 語言(如 Java 和 Perl)的語法。因此,熟悉這些語言的開發(fā)人員在接受 JavaScript 更加寬松的語法時(shí),...

    xiangzhihong 評(píng)論0 收藏0
  • JavaScript 闖關(guān)初探

    摘要:使用元素嵌入代碼時(shí),只需為指定屬性。需要注意的是,帶有屬性的元素不應(yīng)該在其和元素之間再包含額外的代碼。在包含外部文件時(shí),必須將屬性設(shè)置為指向相應(yīng)文件的。所有元素都會(huì)按照他們?cè)陧撁嬷谐霈F(xiàn)的先后順序依次被解析。關(guān)注,獲取最新動(dòng)態(tài)。 當(dāng)學(xué)習(xí)一門新的編程語言的時(shí)候,應(yīng)該邊學(xué)邊做,反復(fù)演練以加深理解。因此,你需要一個(gè) JavaScript 解釋器。幸運(yùn)的是,每一個(gè) Web 瀏覽器都包含一個(gè) Ja...

    atinosun 評(píng)論0 收藏0
  • JavaScript 闖關(guān)

    摘要:本課程之所以叫做闖關(guān)記,是因?yàn)椴糠终鹿?jié)精心設(shè)計(jì)了挑戰(zhàn)關(guān)卡,通過提供更多的實(shí)戰(zhàn)機(jī)會(huì),讓大家可以循序漸進(jìn)地有目的地有挑戰(zhàn)地開展學(xué)習(xí)。課程結(jié)構(gòu)及目錄以下目錄只是初步構(gòu)想,課程結(jié)構(gòu)及內(nèi)容會(huì)根據(jù)實(shí)際情況隨時(shí)進(jìn)行調(diào)整。 為何寫作此課程 stone 主要負(fù)責(zé)基于 Web 的企業(yè)內(nèi)部管理系統(tǒng)的開發(fā),雖然能夠熟練地使用 JavaScript,但隨著對(duì) JavaScript 的理解越來越深,才發(fā)現(xiàn)自己尚...

    curried 評(píng)論0 收藏0
  • JavaScript 闖關(guān)單體內(nèi)置對(duì)象

    摘要:單體內(nèi)置對(duì)象對(duì)內(nèi)置對(duì)象的定義是由實(shí)現(xiàn)提供的不依賴于宿主環(huán)境的對(duì)象,這些對(duì)象在程序執(zhí)行之前就已經(jīng)存在了。還定義了兩個(gè)單體內(nèi)置對(duì)象和。此外,所有原生引用類型的構(gòu)造函數(shù),像和,也都是對(duì)象的屬性。 單體內(nèi)置對(duì)象 ECMA-262 對(duì)內(nèi)置對(duì)象的定義是「由 JavaScript 實(shí)現(xiàn)提供的、不依賴于宿主環(huán)境的對(duì)象,這些對(duì)象在 JavaScript 程序執(zhí)行之前就已經(jīng)存在了」。意思就是說,開發(fā)人員不...

    antyiwei 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<