javascript類型系統之Array
前面的話
數組是一組按序排列的值,相對地,對象的屬性名稱是無序的。從本質上講,數組使用數字作為查找鍵,而對象擁有用戶自定義的屬性名。javascript沒有真正的關聯數組,但對象可用于實現關聯的功能
Array()僅僅是一種特殊類型的Object(),也就是說,Array()實例基本上是擁有一些額外功能的Object()實例。數組可以保存任何類型的值,這些值可以隨時更新或刪除,且數組的大小是動態調整的
數組創建
與Javascript中的大多數對象一樣,可以使用new操作符連同Array()構造函數,或者通過使用字面量語法來創建數組對象
【1】使用Array構造函數(在使用Array構造函數時,也可以省略New操作符),可以將數組實例的值傳遞給構造函數,以逗號分隔作為參數,Array()構造函數可以接收4294967295(大約43億)個參數
如果只有一個參數:若傳遞的是數值,它將用來設置數組的長度;若傳遞的是其他類型的參數,則會創建包含那個值的只有一項的數組
var colors; console.log(colors = new Array(),colors.length);//[] 0 console.log(colors = new Array('red','blue','green'),colors.length);//['red','blue','green'] 3 console.log(colors = new Array(20),colors.length);//[] 20 console.log(colors = new Array('red'),colors.length);//['red'] 1
var foo = new Array(1,2,3); var bar = new Array(100); console.log(foo[0],foo[2]);//1 3 console.log(bar[0],bar.length);//undefined 100
【2】使用數組字面量表示法
var colors = ['red','blue','green']; var colors = [];
//Array構造函數 var myArray1 = new Array('blue','green','orange','red'); console.log(myArray1);//['blue','green','orange','red'] //數組字面量表示法 var myArray2 = ['blue','green','orange','red']; console.log(myArray2);//['blue','green','orange','red']
var colors = [1,2,]; //在IE8及以前中會包含一個三個項目,且每個項目為1、2和undefined的數組。在其他瀏覽器中為只包含1和2的數組 var colors = [,,,]; //在IE8及以前會創建4項的數組,而在其他瀏覽器中會創建3項的數組
數組操作
在讀取和設置數組的值時,要使用方括號并提供相應值的基于0的數字索引
數組的長度length屬性表示數組中值的數量,而數組的數字索引是從0開始的;且length屬性可讀可寫,通過設置數組的Length屬性,可以從數組的末尾移除項或向數組中添加新項。如果設置的長度高于數組中值的實際數量,將向數組中添加undefined值;若將長度值的數量設置為少于數組中的值的數量,可能會刪除數組中的值
var myArray = ['blue','green','orange','red']; console.log(myArray.length);//4 myArray.length = 99; console.log(myArray.length);//99 myArray.length = 1; console.log(myArray[1]);//undefined console.log(myArray);//['blue']
var colors = ['red','blue','green']; colors.length = 2; alert(colors[2]);//undefined colors.length = 4; alert(colors[3]);//undefined
當把一個值放在超出數組大小的位置上時,數組就會重新計算其長度值,即長度值等于最后一項的索引加1,Javascript將會使用undefined值填充當前索引之前的所有索引
var myArray = []; myArray[50] = 'blue'; console.log(myArray.length);//51
var colors = ['red','blue','green']; colors[99] = 'black'; console.log(colors.length);//100
[tips]利用length屬性可以方便地在數組末尾添加新項
colors[colors.length] = 'black';
繼承的方法
toString()
返回由數組中每個值的字符串形式拼接而成的一個以逗號分隔的字符串
valueof()
返回的還是數組
var colors = ['red','blue','green']; console.log(colors.valueOf());//['red','blue','green'] alert(colors.valueOf());//'red,blue,green' alert(colors.toString());//'red,blue,green' alert(colors);//'red,blue,green'[注意]由于alert()要接收字符串參數,它會在后臺調用toString()方法,會得到與toString()方法相同的結果
toLocaleString()
調用該方法時,數組的每一項的值調用的是toLocaleString()方法
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
實例方法
數組轉換
join()
數組繼承的toLocaleString()、toString()、valueOf()方法,在默認情況下都會以逗號分隔的字符形式返回數組項;而join()方法可以使用不同的分隔符來構建這個字符串,join()方法只接收一個參數,用作分隔符的字符串,然后返回包含所有數組項的字符串。如果不給join()方法傳入任何值,或者傳入undefined,則使用逗號作為分隔符
var colors = ['red','green','blue']; console.log(colors.join(','));//'red,green,blue' console.log(colors.join('||'));//'red||green||blue' console.log(colors.join());//'red,green,blue' console.log(colors.join(undefined));//'red,green,blue'[注意]IE7-會使用undefined作為分隔符
[注意]如果數組中的某一項的值是null或者undefined,那么該值在join()、toLocaleString()、toString()和valueOf()方法返回的結果中以空字符串表示
數組檢測
自從ES3做出規定之后,就出現了確定某個對象是不是數組的經典問題。一般的常見方法是使用instance操作符,但該方法有它的局限性;ES5專門新增了isArray()方法來檢測數組
var value = [123]; console.log(value instanceof Array);//true
instanceof操作符的問題在于它假定只有一個全局執行環境,如果網頁中包含多個框架,那實際上就存在兩個以上不同的全局環境,從而存在兩個以上不同版本的Array構造函數。如果從一個框架向另一個框架傳入一個數組,那么傳入的數組與在第二個框架中原生創建的數組分別具有各自不同的構造函數
為了解決該問題,ES5新增了Array.isArray()方法,來最終確定某個值到底是不是數組,而不管它在哪個全局環境中創建的
Array.isArray()
var value = [123]; console.log(Array.isArray(value));//true
棧和隊列
push()
可以接收任意數量的參數,把它們逐個添加到數組末尾,并返回修改后數組的長度
pop()
從數組末尾移除最后一項,減少數組的length值,然后返回移除的項
shift()
移除數組中的第一個項并返回該項,同時數組的長度減1(結合使用shift()和push()可以模擬隊列)
unshift()
在數組前端添加任意個項并返回新數組長度(結合使用unshift()和pop()從相反方向模擬隊列)
[注意]IE7-瀏覽器unshift()方法返回的總是undefined
var colors = []; var count = colors.push('red','green'); console.log(colors,count);//['red','green'] 2 var count = colors.pop(); console.log(colors,count);//['red'] 'green' var count = colors.unshift('white','black'); console.log(colors,count);//["white", "black", "red"] 3 var count = colors.shift(); console.log(colors,count);//["black", "red"] "white"
排序方法
reverse()
反轉數組的順序,返回經過排序之后的數組;而原數組順序也發生改變
var array = [1,2,4,3,5]; console.log(array,array.reverse());//[5,3,4,2,1] [5,3,4,2,1] var array = ['str',true,3]; console.log(array,array.reverse());//[3,true,'str'] [3,true,'str']
sort()
默認情況下,按字符串升序排列數組項,sort方法會調用每個數組項的toString()方法,然后比較得到的字符串排序,返回經過排序之后的數組,而原數組順序也發生改變
var array = [1,2,4,3,5]; console.log(array,array.sort());//[1,2,3,4,5] [1,2,3,4,5] var array = ['3str',3,2,'2']; console.log(array,array.sort());//[2, "2", 3, "3str"] [2, "2", 3, "3str"] var array = [1,5,10,50]; console.log(array,array.sort());//[1, 10, 5, 50] [1, 10, 5, 50]
[注意]sort()方法可以接受一個比較函數作為參數,以便指定哪個值在哪個值的前面。比較函數接收兩個參數,如果第一個參數應該位于第二個參數之前則返回一個負數,如果兩個參數相等則返回0,如果第一個參數應該位于第二個參數之后則返回一個正數
[tips]比較函數
function compare(value1,value2){ if(value1 < value2){ return -1; }else if(value1 > value2){ return 1; }else{ return 0; } } var array = ['5px',50,1,10]; //當數字與字符串比較大小時,字符串'5px'會被轉換成NaN,這樣結果就是false console.log(array.sort(compare));//["5px",1, 10, 50]
對于數值類型或valueOf()方法會返回數值類型的對象類型,比較函數可以簡化為:
function compare(value1,value2){ return value1 - value2; } var array = ['5px',50,1,10]; console.log(array.sort(compare));//["5px",1,10,50] var array = [5,50,1,10]; console.log(array.sort(compare));//[1,5,10,50]
[tips]創建一個隨機數組
function compare(){ return Math.random() - 0.5; } var array = [1,2,3,4,5]; console.log(array.sort(compare));//[2,1,5,4,3]
操作方法
concat()
基于當前數組中的所有項創建一個新數組,先創建當前數組一個副本,然后將接收到的參數添加到這個副本的末尾,最后返回新構建的數組(concat()不影響原數組)
如果不給concat()方法傳遞參數時,它只是復制當前的數組;如果參數是一個或多個數組,則該方法會將這些數組中的每一項都添加到結果數組中;如果傳遞的值不是數組,這些值就會被簡單地添加到結果數組的末尾
var numbers = [1,2]; console.log(numbers,numbers.concat());//[1,2] [1,2] console.log(numbers,numbers.concat([5,4,3],[3,4,5],1,2));//[1,2] [1,2,5,4,3,3,4,5,1,2]
slice()
基于當前數組中的一個或多個項創建一個新數組,接受一個或兩個參數,即要返回項的起始和結束位置,最后返回新數組(slice()不影響原數組)
如果沒有參數,則返回原數組;如果只有一個參數時,slice()方法返回從該參數指定位置開始到當前數組末尾的所有項;若有兩個參數時,該方法返回起始位置和結束位置之間的項,但不包括結束位置的項;若參數為負數時,則用數組長度加負數作為參數;若結束位置小于開始位置,則返回空數組
var numbers = [1,2,3,4,5]; console.log(numbers.slice());//[1,2,3,4,5] console.log(numbers.slice(2));//[3,4,5] console.log(numbers.slice(2,3));//[3] console.log(numbers.slice(-3));//-3+5=2 -> [3,4,5] console.log(numbers.slice(2,1));//[]
splice()
原數組變為修改后的數組,而splice()返回從原數組中刪除的項組成的數組,若無刪除項則返回空數組。若第一個參數為負數時,則用數組長度加負數作為參數;若第二個參數為負數時,則用0作為參數
[1]刪除:兩個參數為要刪除的第一項的位置、要刪除的項數
[2]插入:三個參數為起始位置、0(要刪除的基數)、要插入的項
[3]替換:三個參數為起始位置、要刪除的項數、要插入的項
var numbers = [1,2,3,4,5]; console.log(numbers.splice(),numbers);//[] [1, 2, 3, 4, 5] console.log(numbers.splice(0,2),numbers);//[1,2] [3,4,5] var numbers = [1,2,3,4,5]; console.log(numbers.splice(1,0,11,12),numbers);//[] [1,11,12,2,3,4,5] var numbers = [1,2,3,4,5]; console.log(numbers.splice(1,3,11,12),numbers);//[2,3,4] [1,11,12,5] var numbers = [1,2,3,4,5]; console.log(numbers.splice(-4,3,11,12),numbers);//-4+5=1 -> [2,3,4] [1,11,12,5] var numbers = [1,2,3,4,5]; console.log(numbers.splice(-4,-3,11,12),numbers);//-4+5=1 -> [] [1,11,12,2,3,4,5]
位置方法
ES5為數組實例添加了兩個位置方法indexOf()、lastIndexOf()。這兩個方法都接收兩個參數:要查找的項、表示查找起點位置的索引(可選)。返回第一個滿足條件的查找項在數組中的位置,如果沒有找到則返回-1(位置方法不會影響原數組)
[注意]方法在比較參數時,使用的是全等操作符
indexOf() 從前向后查找
lastIndexOf()
從后向前查找
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]; alert(people.indexOf(person));//-1,因為person和people[0]雖然值相同,但是是兩個引用 alert(morePeople.indexOf(person));//0,因為person和morepeople[0]是同一個引用 alert(morePeople.indexOf({name: 'Nicholas'}));//-1,因為不是同一個引用
[tips]返回滿足條件的項的所有索引值
function allIndexOf(array,value){ var result = []; var pos = array.indexOf(value); if(pos === -1){ return -1; } while(pos > -1){ result.push(pos); pos = array.indexOf(value,pos+1); } return result; } var array = [1,2,3,3,2,1]; console.log(allIndexOf(array,1));//[0,5]
參考資料
[1]Javascript高級程序設計(第3版)
[2]Javascript啟示錄
[3]w3school——Javascript高級教程
[4]慕課網——Javascript進階篇
[5]網易微專業——Javascript程序設計
[6]妙味課堂VIP視頻