摘要:為了維持此規(guī)則不變化,數(shù)組有兩個特殊的行為。運算符對數(shù)組返回并且對于除了函數(shù)以外的所有對象都是如此。解決方案是檢查對象的類屬性,對數(shù)組而言該屬
數(shù)組
數(shù)組是值的有序集合。每個值叫做一個元素,而每個元素在數(shù)組中有一個位置,以數(shù)字表示,稱為索引。
JavaScript 數(shù)組是無類型的,數(shù)組元素可以是任意類型,并且同一個數(shù)組中的不同元素也可能有不同的類型。數(shù)組的元素甚至也可能是對象或其他數(shù)組。
JavaScript 數(shù)組是動態(tài)的,根據(jù)需要它們會增長或縮減,并且在創(chuàng)建數(shù)組時無須聲明一個固定的大小或者在數(shù)組大小變化時無須重新分配空間。
JavaScript 數(shù)組可能是稀疏的,數(shù)組元素的索引不一定要連續(xù)的,它們之間可以有空缺。每個 JavaScript 數(shù)組都有一個 length 屬性。針對非稀疏數(shù)組,該屬性就是數(shù)組元素的個數(shù)。針對稀疏數(shù)組,length 比所有元素的索引要大。
JavaScript 數(shù)組是 JavaScript 對象的特殊形式,數(shù)組索引實際上和碰巧是整數(shù)的屬性名差不多。通常,數(shù)組的實現(xiàn)是經(jīng)過優(yōu)化的,用數(shù)字索引來訪問數(shù)組元素一般來說比訪問常規(guī)的對象屬性要快很多。
數(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個數(shù)值的數(shù)組 var misc = [1.1, true, "a"]; // 3個不同類型的元素 // 數(shù)組直接量中的值不一定要是常量,可以是任意的表達(dá)式 var base = 1024; var table = [base, base+1, base+2, base+3]; // 也可以包含對象直接量或其他數(shù)組直接量 var b = [[1, {x:1, y:2}], [2, {x:3, y:4}]];
注意,不要忽略數(shù)組字面量的最后一個元素,僅以逗號結(jié)尾。下面幾個案例,在不同的瀏覽器下,可能會被識別成2個元素,也有可能識別成3個元素,而造成程序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ù) var a = new Array(); // 調(diào)用時有一個數(shù)值參數(shù),它指定長度 var a = new Array(10); // 顯式指定多個數(shù)組元素或者數(shù)組的一個非數(shù)值元素 var a = new Array(5, 4, 3, 2, 1, "testing");數(shù)組元素的讀和寫
使用 [] 操作符來訪問數(shù)組中的一個元素。數(shù)組的引用位于方括號的左邊。方括號中是一個返回非負(fù)整數(shù)值的任意表達(dá)式。使用該語法既可以讀又可以寫數(shù)組的一個元素。例如:
var a = ["world"]; // 從一個元素的數(shù)組開始 var value = a[0]; // 讀第0個元素 a[1] = 3.14; // 寫第1個元素 var i = 2; a[i] = 3; // 寫第2個元素 a[i + 1] = "hello"; // 寫第3個元素 a[a[i]] = a[0]; // 讀第0個和第2個元素,寫第3個元素
請記住,數(shù)組是對象的特殊形式,可以為其創(chuàng)建任意名字的屬性。但如果使用的屬性是數(shù)組的索引,數(shù)組的特殊行為就是將根據(jù)需要更新它們的length屬性值。
注意,可以使用負(fù)數(shù)或非整數(shù)來索引數(shù)組。這種情況下,數(shù)值轉(zhuǎn)換為字符串,字符串作為屬性名來用。既然名字不是非負(fù)整數(shù),它就只能當(dāng)做常規(guī)的對象屬性,而非數(shù)組的索引。同樣,如果湊巧使用了是非負(fù)整數(shù)的字符串,它就當(dāng)做數(shù)組索引,而非對象屬性。當(dāng)使用的一個浮點數(shù)和一個整數(shù)相等時情況也是一樣的。例如:
a[-1.23] = true; // 這將創(chuàng)建一個名為"-1.23"的屬性 a["1000"] = 0; // 這是數(shù)組的第1001個元素 a[1.000] // 和 a[1] 相等
事實上數(shù)組索引僅僅是對象屬性名的一種特殊類型,這意味著 JavaScript 數(shù)組沒有「越界」錯誤的概念。當(dāng)試圖查詢?nèi)魏螌ο笾胁淮嬖诘膶傩詴r,不會報錯,只會得到 undefined 值。
稀疏數(shù)組稀疏數(shù)組就是包含從0開始的不連續(xù)索引的數(shù)組。通常,數(shù)組的 length 屬性值代表數(shù)組中元素的個數(shù)。如果數(shù)組是稀疏的,length 屬性值大于元素的個數(shù)??梢杂?Array() 構(gòu)造函數(shù)或簡單地指定數(shù)組的索引值大于當(dāng)前的數(shù)組長度來創(chuàng)建稀疏數(shù)組。
a = new Array(5); // 數(shù)組沒有元素,但是 a.length = 5 a = []; // 創(chuàng)建一個空數(shù)組,a.length = 0 a[1000] = 0; // 添加一個元素,a.length 被自動更新為1001
足夠稀疏的數(shù)組通常在實現(xiàn)上比稠密的數(shù)組更慢、內(nèi)存利用率更高,在這樣的數(shù)組中查找元素的時間與常規(guī)對象屬性的查找時間一樣長。
需要注意的是,當(dāng)省略數(shù)組直接量中的值時(使用連續(xù)的逗號,比如 [1,,3] ),這時所得到的數(shù)組也是稀疏數(shù)組,省略掉的值是不存在的:
var a1 = [,"1","2"]; // 此數(shù)組長度是3 var a2 = [undefined]; // 此數(shù)組包含一個值為 undefined 的元素 console.log(0 in a1); // false,a1 在索引0處沒有元素 console.log(0 in a2); // true,a2 在索引0處有一個值為 undefined 的元素
了解稀疏數(shù)組是了解 JavaScript 數(shù)組的真實本質(zhì)的一部分。盡管如此,實際上你所碰到的絕大多數(shù) JavaScript 數(shù)組不是稀疏數(shù)組。并且,如果你確實碰到了稀疏數(shù)組,你的代碼很可能像對待非稀疏數(shù)組一樣來對待它們,只不過它們包含一些 undefined 值。
數(shù)組長度每個數(shù)組有一個 length 屬性,就是這個屬性使其區(qū)別于常規(guī)的 JavaScript 對象。針對稠密(也就是非稀疏)數(shù)組,length 屬性值代表數(shù)組中元素的個數(shù)。其值比數(shù)組中最大的索引大1。例如:
[].length // 0,數(shù)組沒有元素 ["a","b","c"].length // 3,最大的索引為2,length 為3
當(dāng)數(shù)組是稀疏的時,length 屬性值大于元素的個數(shù)。而且關(guān)于此我們可以說的一切也就是數(shù)組長度保證大于它每個元素的索引值?;蛘?,換一種說法,在數(shù)組中(無論稀疏與否)肯定找不到一個元素的索引值大于或等于它的長度。為了維持此規(guī)則不變化,數(shù)組有兩個特殊的行為。
第一個如同上面的描述:如果為一個數(shù)組元素賦值,它的索引 i 大于或等于現(xiàn)有數(shù)組的長度時,length 屬性的值將設(shè)置為 i+1。
第二個特殊的行為就是設(shè)置 length 屬性為一個小于當(dāng)前長度的非負(fù)整數(shù) n 時,當(dāng)前數(shù)組中那些索引值大于或等于 n 的元素將從中刪除。例如:
a = [1,2,3,4,5]; // 從5個元素的數(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ù)組中添加新的元素,它只是在數(shù)組尾部創(chuàng)建一個空的區(qū)域。
在 ECMAScript 5 中,可以用 Object.defineProperty() 讓數(shù)組的 length 屬性變成只讀的。例如:
a = [1,2,3]; // 從3個元素的數(shù)組開始 Object.defineProperty(a, "length", {writable: false}); // 讓 length 屬性只讀 a.length = 0; // a 不會改變數(shù)組元素的添加和刪除
我們已經(jīng)見過添加數(shù)組元素最簡單的方法,為新索引賦值。例如:
a = [] // 開始是一個空數(shù)組 a[0] = "zero"; // 然后向其中添加元素 a[1] = "one";
也可以使用 push() 方法在數(shù)組末尾增加一個或多個元素。例如:
a = []; // 開始是一個空數(shù)組 a.push("zero"); // 在末尾添加一個元素。a = ["zero"] a.push("one", "two"); // 再添加兩個元素。a = ["zero", "one", "two"]
可以像刪除對象屬性一樣使用 delete 運算符來刪除數(shù)組元素。例如:
a = [1,2,3]; delete a[1]; // a在索引1的位置不再有元素 1 in a // => false: 數(shù)組索引1并未在數(shù)組中定義 a.length // => 3: delete操作并不影響數(shù)組長度
注意,對一個數(shù)組元素使用 delete 不會修改數(shù)組的 length 屬性,也不會將元素從高索引處移下來填充已刪除屬性留下的空白。如果從數(shù)組中刪除一個元素,它就變成稀疏數(shù)組。
數(shù)組遍歷使用 for 循環(huán)是遍歷數(shù)組元素最常見的方法。例如:
var keys = Object.keys(o); // 獲得 o 對象屬性名組成的數(shù)組 var values = [] // 在數(shù)組中存儲匹配屬性的值 for(var i = 0; i < keys.length; i++) { // 對于數(shù)組中每個索引 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)每次將一個可枚舉的屬性名(包括數(shù)組索引)賦值給循環(huán)變量,不存在的索引將不會遍歷到。例如:
for(var index in sparseArray) { var value = sparseArray[index]; // 此處可以使用索引和值做一些事情 }
但由于 for-in 循環(huán)能夠枚舉繼承的屬性名,如添加到 Array.prototype 中的方法?;谶@個原因,在數(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)以不同的順序遍歷對象的屬性。通常數(shù)組元素的遍歷實現(xiàn)是升序的,但不能保證一定是這樣的。如果數(shù)組同時擁有對象屬性和數(shù)組元素,返回的屬性名很可能是按照創(chuàng)建的順序而非數(shù)值的大小順序。如何處理這個問題的實現(xiàn),各個瀏覽器都不相同,如果算法依賴于遍歷的順序,那么最好不要使用 for-in 而用常規(guī)的 for 循環(huán)。
ECMAScript 5 定義了一些遍歷數(shù)組元素的新方法,按照索引的順序按個傳遞給定義的一個函數(shù)。這些方法中最常用的就是 forEach() 方法。例如:
var data = [1,2,3,4,5]; // 這是需要遍歷的數(shù)組 var sumOfSquares = 0; // 要得到數(shù)據(jù)的平方和 data.forEach(function(x) { // 把每個元素傳遞給此函數(shù) sumOfSquares += x*x; // 平方相加 }); console.log(sumOfSquares); // 55,1 + 4 + 9 + 16 + 25數(shù)組檢測
給定一個未知的對象,判定它是否為數(shù)組通常非常有用。在 ECMAScript 5 中,可以使用 Array.isArray() 函數(shù)來做這件事情。例如:
Array.isArray([]) // true Array.isArray({}) // false
但是,在 ECMAScript 5 以前,要區(qū)分?jǐn)?shù)組和非數(shù)組對象很困難。typeof 運算符對數(shù)組返回 "object"(并且對于除了函數(shù)以外的所有對象都是如此)。instanceof 操作符也只能用于簡單的情形。例如:
[] instanceof Array // true ({}) instanceof Array // false
使用 instanceof 的問題是在 Web 瀏覽器中有可能有多個窗體存在。每個窗體都有自己的 JavaScript 環(huán)境,有自己的全局對象。并且,每個全局對象有自己的一組構(gòu)造函數(shù)。因此一個窗體中的對象將不可能是另外窗體中的構(gòu)造函數(shù)的實例。窗體之間的混淆不常發(fā)生,但這個問題足已證明 instanceof 操作符不能視為一個可靠的數(shù)組檢測方法。
解決方案是檢查對象的類屬性,對數(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)換方法所有對象都具有 valueOf()、 toString() 和 toLocaleString() 方法。他們的用途如下:
valueOf():當(dāng)調(diào)用數(shù)組的 valueOf() 方法,會返回 Array 對象的原始值。valueOf() 方法通常由 JavaScript 在后臺自動調(diào)用,并不顯式地出現(xiàn)在代碼中。
toString():當(dāng)調(diào)用數(shù)組的 toString() 方法,會返回以逗號分隔數(shù)組中每個值的字符串。為了創(chuàng)建這個字符串會調(diào)用數(shù)組每一項的 toString() 方法。
toLocaleString():當(dāng)調(diào)用數(shù)組的 toLocaleString() 方法,會返回以逗號分隔數(shù)組中每個值的字符串。為了創(chuàng)建這個字符串會調(diào)用數(shù)組每一項的 toLocaleString() 方法。
如以下代碼所示:
var colors = ["red", "blue", "green"]; // 創(chuàng)建一個包含3個字符串的數(shù)組 console.log(colors); // ["red", "blue", "green"] console.log(colors.valueOf()); // ["red", "blue", "green"] console.log(colors.toString()); // red,blue,green alert(colors.valueOf()); // red,blue,green
在這里,我們首先顯式地調(diào)用了 colors 和 colors.valueOf(),返回的都是數(shù)組對象。然后,我們又顯式地調(diào)用了 toString() 方法,返回了以逗號分隔數(shù)組中每個值的字符串。最后一行代碼直接將 colors.valueOf() 傳遞給了 alert()。由于 alert()要接收字符串參數(shù),所以它會在后臺調(diào)用 toString() 方法,由此會得到與直接調(diào)用 toString() 方法相同的結(jié)果。
當(dāng)調(diào)用數(shù)組的 toLocaleString() 方法時,它會創(chuàng)建以逗號分隔數(shù)組中每個值的字符串。與 toString() 方法唯一的不同之處在于,這一次為了取得每一項的值,調(diào)用的是每一項的 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]; console.log(people.toString()); // Nicholas,Greg console.log(people.toLocaleString()); // Nikolaos,Grigorios
數(shù)組繼承的 toLocaleString() 和 toString() 方法,在默認(rèn)情況下都會以逗號分隔的字符串的形式返回數(shù)組項。而如果使用 join() 方法,則可以使用不同的分隔符來構(gòu)建這個字符串。join() 方法只接收一個參數(shù),即用作分隔符的字符串,然后返回包含所有數(shù)組項的字符串。例如:
var colors = ["red", "green", "blue"]; console.log(colors.join(",")); // red,green,blue console.log(colors.join("||")); // red||green||blue
如果數(shù)組中的某一項的值是 null 或者 undefined,那么該值在 join()、toLocaleString()、toString() 和 valueOf() 方法返回的結(jié)果中以空字符串表示。
數(shù)組和字符串之間是可以互相轉(zhuǎn)換的,使用 String 對象的原型方法 split() 即可實現(xiàn)該功能。這個方法可以基于指定的分隔符將一個字符串分割成多個子字符串,并將結(jié)果放在一個數(shù)組中。例如:"red,blue,green,yellow".split(",") 結(jié)果是 ["red", "blue", "green", "yellow"]。更多 split() 方法的說明會在后面章節(jié)中詳細(xì)介紹。棧方法
棧是一種 LIFO(Last-In-First-Out,后進(jìn)先出)的數(shù)據(jù)結(jié)構(gòu),也就是最新添加的項最早被移除。push() 方法可以接收任意數(shù)量的參數(shù),把它們逐個添加到數(shù)組末尾,并返回修改后數(shù)組的長度。而 pop() 方法則從數(shù)組末尾移除最后一項,減少數(shù)組的 length 值,然后返回移除的項。結(jié)合 push() 和 pop() 方法,就可以像棧一樣使用數(shù)組。例如:
var colors = []; // 創(chuàng)建一個數(shù)組 var count = colors.push("red", "green"); // 推入兩項 console.log(count); // 2,數(shù)組的長度 count = colors.push("black"); // 推入另一項 console.log(count); // 3,數(shù)組的長度 var item = colors.pop(); // 取得最后一項 console.log(item); // "black" console.log(colors.length); // 2,數(shù)組的長度隊列方法
隊列是一種 FIFO(First-In-First-Out,先進(jìn)先出)的數(shù)據(jù)結(jié)構(gòu),隊列在列表的末端添加項,從列表的前端移除項。shift() 方法則從數(shù)組前端移除第一項,減少數(shù)組的 length 值,然后返回移除的項。結(jié)合 push() 和 shift() 方法,就可以像隊列一樣使用數(shù)組。例如:
var colors = []; // 創(chuàng)建一個數(shù)組 var count = colors.push("red", "green"); // 推入兩項 console.log(count); // 2,數(shù)組的長度 count = colors.push("black"); // 推入另一項 console.log(count); // 3,數(shù)組的長度 var item = colors.shift(); // 取得第一項 console.log(item); // "red" console.log(colors.length); // 2,數(shù)組的長度
JavaScipt 還為數(shù)組提供了一個 unshift() 方法。顧名思義,unshift() 與 shift() 的用途相反,它能在數(shù)組前端添加任意個項并返回新數(shù)組的長度。因此,同時使用 unshift() 和 pop() 方法,可以從相反的方向來模擬隊列,即在數(shù)組的前端添加項,從數(shù)組末端移除項。
重排序方法數(shù)組中有兩個重排序的方法: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() 方法在排序的過程中會調(diào)用每個數(shù)組元素的 toString(),然后比較得到的字符串,以確定如何排序。即使數(shù)組中的每一項都是數(shù)值,sort() 方法比較的也是字符串,例如:
var values = [0, 1, 5, 10, 15]; values.sort(); console.log(values); // 0,1,10,15,5
這種排序方式在很多情況下都不是最佳方案,因此 sort() 方法可以接收一個比較函數(shù)作為參數(shù),以便我們指定哪個值位于哪個值的前面,以下就是一個簡單的比較函數(shù)。例如:
function compare(value1, value2) { if (value1 < value2) { return -1; } else if (value1 > value2) { return 1; } else { return 0; } }
這個比較函數(shù)接收兩個參數(shù),如果第一個參數(shù)應(yīng)該位于第二個之前則返回一個負(fù)數(shù),如果兩個參數(shù)相等則返回0,如果第一個參數(shù)應(yīng)該位于第二個之后則返回一個正數(shù)。它可以適用于大多數(shù)情況,只要將其作為參數(shù)傳遞給 sort() 方法即可。例如:
var values = [10, 5, 1, 0, 15]; values.sort(compare); console.log(values); // 0,1,5,10,15
對于數(shù)值類型或者其 valueOf() 方法會返回數(shù)值類型的對象類型,可以使用一個更簡單的比較函數(shù)。這個函數(shù)只要用第二個值減第一個值即可。例如:
function compare(value1, value2){ return value2 - value1; }
由于比較函數(shù)通過返回一個小于零、等于零或大于零的值來影響排序結(jié)果,因此減法操作就可以適當(dāng)?shù)靥幚硭羞@些情況。
操作方法JavaScript 為操作已經(jīng)包含在數(shù)組中的元素提供了很多方法。其中,concat() 方法可以基于當(dāng)前數(shù)組中的所有項創(chuàng)建一個新數(shù)組。具體來說,這個方法會先創(chuàng)建當(dāng)前數(shù)組一個副本,然后將接收到的參數(shù)添加到這個副本的末尾,最后返回新構(gòu)建的數(shù)組。在沒有給 concat() 方法傳遞參數(shù)的情況下,它只是復(fù)制當(dāng)前數(shù)組并返回副本。如果傳遞給 concat() 方法的是一或多個數(shù)組,則該方法會將這些數(shù)組中的每一項都添加到結(jié)果數(shù)組中。如果傳遞的值不是數(shù)組,這些值就會被簡單地添加到結(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
下一個方法是 slice(),它能夠基于當(dāng)前數(shù)組中的一或多個項創(chuàng)建一個新數(shù)組。slice() 方法可以接受一或兩個參數(shù),即要返回項的起始和結(jié)束位置。在只有一個參數(shù)的情況下,slice() 方法返回從該參數(shù)指定位置開始到當(dāng)前數(shù)組末尾的所有項。如果有兩個參數(shù),該方法返回起始和結(jié)束位置之間的項,但不包括結(jié)束位置的項。注意,slice() 方法不會影響原始數(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ù)中有一個負(fù)數(shù),則用數(shù)組長度加上該數(shù)來確定相應(yīng)的位置。例如,在一個包含5項的數(shù)組上調(diào)用 slice(-2,-1) 與調(diào)用 slice(3,4) 得到的結(jié)果相同。如果結(jié)束位置小于起始位置,則返回空數(shù)組。
下一個方法是 splice(),它的主要用途是向數(shù)組的中部插入元素,主要有以下3種使用方式。
刪除:可以刪除任意數(shù)量的項,只需指定2個參數(shù):起始位置和要刪除元素的數(shù)量。例如,splice(0,2) 會刪除數(shù)組中的前兩項。
插入:可以向指定位置插入任意數(shù)量的項,只需提供3個參數(shù):起始位置、0(要刪除元素的數(shù)量)和要插入的元素。如果要插入多個元素,可以再傳入第四、第五,以至任意多個元素。例如,splice(2,0,"red","green") 會從當(dāng)前數(shù)組的位置2開始插入字符串 "red" 和 "green"。
替換:可以向指定位置插入任意數(shù)量的項,且同時刪除任意數(shù)量的項,只需指定3個參數(shù):起始位置、要刪除元素的數(shù)量和要插入的元素。插入的項數(shù)不必與刪除的項數(shù)相等。例如,splice (2,1,"red","green")會刪除當(dāng)前數(shù)組位置2的項,然后再從位置2開始插入字符串 "red" 和 "green"。
splice() 方法始終都會返回一個數(shù)組,該數(shù)組中包含從原始數(shù)組中刪除的項(如果沒有刪除任何項,則返回一個空數(shù)組)。下面的代碼展示了上述3種使用 splice() 方法的方式。例如:
var colors = ["red", "green", "blue"]; var removed = colors.splice(0,1); // 刪除第一項 console.log(colors); // green,blue console.log(removed); // red,返回的數(shù)組中只包含一項 removed = colors.splice(1, 0, "yellow", "orange"); // 從位置1開始插入兩項 console.log(colors); // green,yellow,orange,blue console.log(removed); // 返回的是一個空數(shù)組 removed = colors.splice(1, 1, "red", "purple"); // 插入兩項,刪除一項 console.log(colors); // green,red,purple,orange,blue console.log(removed); // yellow,返回的數(shù)組中只包含一項位置方法
ECMAScript 5 為數(shù)組實例添加了兩個位置方法:indexOf() 和 lastIndexOf()。這兩個方法都接收兩個參數(shù):要查找的項和(可選的)表示查找起點位置的索引。其中,indexOf() 方法從數(shù)組的開頭(位置0)開始向后查找,lastIndexOf() 方法則從數(shù)組的末尾開始向前查找。
這兩個方法都返回要查找的項在數(shù)組中的位置,或者在沒找到的情況下返回 -1。在比較第一個參數(shù)與數(shù)組中的每一項時,會使用全等操作符;也就是說,要求查找的項必須嚴(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個迭代方法。每個方法都接收兩個參數(shù):要在每一項上運行的函數(shù)和(可選的)運行該函數(shù)的作用域?qū)ο蟆魅脒@些方法中的函數(shù)會接收三個參數(shù):數(shù)組項的值、該項在數(shù)組中的位置和數(shù)組對象本身。根據(jù)使用的方法不同,這個函數(shù)執(zhí)行后的返回值可能會也可能不會影響訪問的返回值。以下是這5個迭代方法的作用。
every(),對數(shù)組中的每一項運行給定函數(shù),如果該函數(shù)對每一項都返回 true ,則返回 true。
filter(),對數(shù)組中的每一項運行給定函數(shù),返回該函數(shù)會返回 true 的項組成的數(shù)組。
forEach(),對數(shù)組中的每一項運行給定函數(shù)。這個方法沒有返回值。
map(),對數(shù)組中的每一項運行給定函數(shù),返回每次函數(shù)調(diào)用的結(jié)果組成的數(shù)組。
some(),對數(shù)組中的每一項運行給定函數(shù),如果該函數(shù)對任一項返回 true ,則返回 true。
以上方法都不會修改數(shù)組中的包含的值。在這些方法中,最相似的是 every() 和 some(),它們都用于查詢數(shù)組中的項是否滿足某個條件。對 every() 來說,傳入的函數(shù)必須對每一項都返回 true,這個方法才返回 true;否則,它就返回 false。而 some()方法則是只要傳入的函數(shù)對數(shù)組中的某一項返回 true,就會返回 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ù)組中包含的某一項。例如:
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() 也返回一個數(shù)組,而這個數(shù)組的每一項都是在原始數(shù)組中的對應(yīng)項上運行傳入函數(shù)的結(jié)果。例如,可以給數(shù)組中的每一項乘以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]
最后一個方法是 forEach(),它只是對數(shù)組中的每一項運行傳入的函數(shù)。這個方法沒有返回值,本質(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 還新增了兩個縮小數(shù)組的方法:reduce() 和 reduceRight()。這兩個方法都會迭代數(shù)組的所有項,然后構(gòu)建一個最終返回的值。其中,reduce() 方法從數(shù)組的第一項開始,逐個遍歷到最后。而 reduceRight() 則從數(shù)組的最后一項開始,向前遍歷到第一項。
這兩個方法都接收兩個參數(shù):一個在每一項上調(diào)用的函數(shù)和(可選的)作為縮小基礎(chǔ)的初始值。傳給 reduce() 和 reduceRight() 的函數(shù)接收4個參數(shù):前一個值、當(dāng)前值、項的索引和數(shù)組對象。這個函數(shù)返回的任何值都會作為第一個參數(shù)自動傳給下一項。第一次迭代發(fā)生在數(shù)組的第二項上,因此第一個參數(shù)是數(shù)組的第一項,第二個參數(shù)就是數(shù)組的第二項。
使用 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ù)組的第三項)。這個過程會持續(xù)到把數(shù)組中的每一項都訪問一遍,最后返回結(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ù)組。除此之外,它們完全相同。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/106922.html
摘要:寫在開頭本篇是小紅書筆記的第六篇,也許你會奇怪第六篇筆記才寫語法基礎(chǔ),筆者是不是穿越了??梢撇焦P者的文章中替換方式參考文檔高級程序設(shè)計作者以樂之名本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。 showImg(https://segmentfault.com/img/bVblGMc?w=600&h=400); 寫在開頭 本篇是小紅書筆記的第六篇,也許你會奇怪第六篇筆記才寫語法基礎(chǔ),筆者是不是穿越了。...
摘要:年月歐洲計算機(jī)制造商協(xié)會發(fā)表了標(biāo)準(zhǔn),它是的一個擴(kuò)延,它也被稱為年月首版年月日截止發(fā)布日期,的官方名稱是,國際意在更頻繁地發(fā)布包含小規(guī)模增量更新的新版本,下一版本將于年發(fā)布,命名為。 前端最基礎(chǔ)的就是 HTML+CSS+Javascript。掌握了這三門技術(shù)就算入門,但也僅僅是入門,現(xiàn)在前端開發(fā)的定義已經(jīng)遠(yuǎn)遠(yuǎn)不止這些。前端小課堂(HTML/CSS/JS),本著提升技術(shù)水平,打牢基礎(chǔ)知識的...
摘要:在標(biāo)簽中添加屬性,本質(zhì)上是跟在標(biāo)簽里面寫屬性時一樣的,所以屬性值最終都會編譯為字符串類型。這個節(jié)點包括很多,比如,以及一些方法等方法。一個對象有很多,該集合名字為,里面有其他以及,里面有很多。 一、變量類型和計算 JS中使用typeof能得到哪些類型 變量類型 值類型:變量本身就是含有賦予給它的數(shù)值的,它的變量本身及保存的數(shù)據(jù)都存儲在棧的內(nèi)存塊當(dāng)中 引用類型:引用類型當(dāng)然是分配到...
摘要:在對象的構(gòu)造函數(shù)中,將一個函數(shù)作為第一個參數(shù)。二對象中的方法,可以接收構(gòu)造函數(shù)中處理的狀態(tài)變化,并分別對應(yīng)執(zhí)行。 showImg(https://segmentfault.com/img/remote/1460000008932857); Promise的重要性我認(rèn)為我沒有必要多講,概括起來說就是必須得掌握,而且還要掌握透徹。這篇文章的開頭,主要跟大家分析一下,為什么會有Promise...
摘要:前端最基礎(chǔ)的就是。一個朋友的問題,監(jiān)測下載進(jìn)度。這節(jié)主要是講如何使用,以及前端下載的核心操作。下載文件,并顯示進(jìn)度條。下載文件,并顯示進(jìn)度條下載文件上面已經(jīng)實現(xiàn)了,那我們先說說如何顯示進(jìn)度條。實現(xiàn)代碼如下,我們操作成讀流,然后統(tǒng)計長度。 前端最基礎(chǔ)的就是 HTML+CSS+Javascript。掌握了這三門技術(shù)就算入門,但也僅僅是入門,現(xiàn)在前端開發(fā)的定義已經(jīng)遠(yuǎn)遠(yuǎn)不止這些。前端小課堂(H...
閱讀 2060·2021-11-23 09:51
閱讀 3353·2021-09-28 09:36
閱讀 1120·2021-09-08 09:35
閱讀 1758·2021-07-23 10:23
閱讀 3258·2019-08-30 15:54
閱讀 2998·2019-08-29 17:05
閱讀 438·2019-08-29 13:23
閱讀 1294·2019-08-28 17:51