封面圖片來自Google
除了Object外,Array型別恐怕是Js中最常用的型別了
Js中陣列的特點:
- 有序表
- 可以儲存任意型別資料
- 陣列長度是動態的(可以隨資料的新增自動增長內容)
1、建立陣列
建立陣列的兩種基本方式:建構函式Array()
和陣列字面量[]
/ * 建構函式 */
var arr1 = new Array() // 建立一個空陣列
var arr2= new Array(3) // 建立一個length為3的空陣列
var arr2= new Array('ok') // ['ok']
var arr2= new Array(3,5) // [3,5]
var arr3= Array('ok') // ['ok'] 陣列的建立省略new,效果也是相同的,區別於物件
/* 陣列字面量 */
var arr4=[] //空陣列
var arr5=[3] // [3]
var arr5=[3,'array',{'name':'Leo'}] // [3,'array',{'name':'Leo'}]
/* 不要像下面這樣!! */
var arrNotRecommend1=[1,2,] //會建立一個2項或者3項的陣列
var arrNotRecommend2=[, , , , ] //會建立一個4項或者5項的陣列
//原因是老版本(IE8-)的瀏覽器在陣列字面量的實現上存在BUG
複製程式碼
對於Array()
建立陣列有些缺陷(坑),因為給的引數個數(0,1,2+)不同都會導致Array()
有不同的行為,所以一般建議用陣列字面量,或者Array.of()
(ES6方法,後面提到)
2、訪問和設定陣列的成員
2.1、使用 arr[idx]
方括號訪問
索引是以 0
開始的,以之前的 arr5
為例:
arr5[0] // 3 訪問第一項
arr5[2] // {'name':'Leo'}
arr5[2]='edit' // 修改第三項資料為 ’edit‘
arr5[3]='add' // 新增第四項為 'add'
複製程式碼
2.2、length屬性 :資料項個數
Js陣列的 length
屬性是可讀可寫的,所以可以通過陣列的 length
屬性對其進行加長和移除項的操作
var tryArrLen=['data1',2,'data3']
tryArrLen.length // 3
tryArrLen.length=4 //陣列新增一項,該項預設會為'undefined'
tryArrLen[5]='add' //陣列新增一項,值為'add'
tryArrLen[tryArrLen.length]='data' //利用'length'屬性向陣列末尾新增元素
tryArrLen.length=2 //陣列項減少到2,會刪除第三項'data3'
tryArrLen[2] //此時再次訪問第三項,也會為undefined,不過原因是第三項已經被刪除了
複製程式碼
2.3、length屬性騷操作
var tryArrLen2=[1,2,3]
tryArrLen2[99]=100 //在第一百項新增一個資料 '100'
複製程式碼
此時 tryArrLen2.length=?
,答案是 100
,並且從第四項到第九十九項的資料都是空位,簡單的理解為 undifined
。
具體來說ES6的陣列方法都把空位作為undefined
,而ES5陣列方法中對空位的處理不太統一,參考陣列的空位
var tryArrLen3=[1,2,3]
tryArrLen3.length=4294967296 // RangeError: Invalid array length
複製程式碼
Js陣列最多可以包含 4294967295
項,超出了,報 RangeError
。
3、陣列檢測
一個經典問題:如何檢測某個物件是不是陣列?
3.1、常規操作
方法 | 不足 |
---|---|
arr isInstanceOf Array |
arr 必須和Array 在同一個全域性作用域。多個全域性環境時候(比如frame)就是妖怪。 |
Array.isArray(arr) |
對老版本瀏覽器相容性不好 |
3.2、騷操作
Object.prototype.toString.call(arr) == "[Object Array]"
複製程式碼
任何一個物件上呼叫 Object
原生的 toString()
方法,都會返回一個
[Object NativeConstructorName]
的字串。
注意!!前提是
Object.prototype.toString()
本身也沒有被修改過,因為其也有可能被修改...
4、轉換方法
4.1、物件方法
valueOf()
:返回陣列本身toString()
:返回陣列的字串表示。每個值以字串表示,並以逗號,
拼接toLocaleString()
:和toString()
基本相同,區別在於輸出的是本地化的、特定語言環境的字串
/* 將下列程式碼修改 'zh-cn'為其他語言,執行一下,你就明白了 */
var array1 = [1, 'a', new Date('21 Dec 1997 14:12:00 UTC')];
var localeString = array1.toLocaleString('zh-cn', {timeZone: "UTC"});
console.log(localeString);
// expected output: "1,a,12/21/1997, 2:12:00 PM",
// This assumes "en" locale and UTC timezone - your results may vary
複製程式碼
4.2、join()
和toString()
基本相同,區別在於可以指定以什麼字串進行拼接
let arr=[1,2,3]
arr.join('+') // "1+2+3"
複製程式碼
5、棧和佇列方法
push()
:接收任意個數的引數,按順序新增到陣列末尾pop()
:移除陣列的最後一項(不接收引數),並返回該項,陣列length-1
shift()
:移除陣列的第一項(不接收引數),並返回該項,陣列length-1
unshift()
:接收任意個數的引數,按順序新增到陣列前端
將這四個方法進行組合就可以實現棧和佇列的基本操作
/* 棧 */
push()+pop()
unshift()+shift()
/* 佇列 */
push()+shift()
unshift()+pop()
複製程式碼
6、重排序方法
6.1、reverse()
反轉陣列的順序
6.2、sort()
預設呼叫每個陣列項的toString
方法,在進行排序。可以接收一個比較函式作為排序的引數
比較函式接收兩個形參,表示陣列中相鄰的兩個數,比如val1
,val2
。
返回值可以為
- 負數,即'val1'排在
val2
之前 - 0,不改變排序
- 正數,'val1'排在
val2
之後
所以在比較函式內可以寫排序邏輯,比較常用的:
function compare(val1,val2){
return val2-val1
}
...
arr.sort(compare) //降序排列
複製程式碼
7、操作方法
7.1、concat()
建立當前陣列的副本,並將接收的引數新增到副本的末尾,並返回一個新陣列(沒有引數即返回副本本身)
- 陣列淺拷貝
- 合併陣列
若concat()
的引數是陣列,則會將引數陣列的每一項(考慮當陣列中的項是陣列或物件的情況)新增到結果陣列末尾。
若引數不是陣列型別,則是簡單新增到結果陣列的末尾。
7.2、slice()
對陣列進行切片操作,不改變原陣列,返回一個新陣列。
接收一個或兩個數字引數:
- 1個引數:返回從該位置到陣列末尾的切片,即
[ 引數 , arr.length)
- 2個引數:返回引數1位置到引數2位置-1的切片,即
[ 引數1 , 引數2 )
當引數為負數時,則可以將length
加上該引數來確定其正數位置。即負數從陣列末尾算起(最後一位為 -1
,依次類推)
7.3、splice()
splice()
接收 2
個或者 2+n
個引數,返回值永遠為一個陣列,包含從原陣列中刪除的項(沒有刪除返回空陣列)。splice()
操作會改變原陣列。
splice( startPos, delCount , el1,el2,..eln )
複製程式碼
startPos
: 起始位置delCount
:(從起始位置起)刪除的項數el
:(可選引數)插入或者替換的項
主要可以實現陣列的刪除、插入和替換操作。
- 刪除 只需指定兩個引數
startPos
、delCount
- 插入 指定
startPos
,且delCount=0
,後面跟需要插入的若干個元素 - 替換 指定
startPos
,delCount
為(從startPos
開始)要替換的元素個數,後面給需要替換的若干個元素。(注:delCount
可以和引數中元素個數不一樣,多餘的就變為刪除或者插入操作)。
8、位置方法
indexOf()
:從前往後找lastIndexOf()
:從後往前找
都接收兩個引數:待查詢的項和(可選)查詢的起始位置。 返回值為待查詢的項在陣列中的位置,沒有找到則返回-1
注:查詢時候使用的是
===
進行判斷
9、迭代方法
迭代方法都不可以使用break
或者continue
進行中斷。
forEach()
:對陣列每一項執行指定函式,沒有返回值map()
:對陣列每一項執行指定函式,返回return
的結果組成的新陣列。filter()
:對陣列每一項執行指定函式,返回return
的結果為true
的成員組成的新陣列。every()
:對陣列每一項執行指定函式,若指定函式對每一項都return
的值為true,則返回true
,否則false
some()
:對陣列每一項執行指定函式,若指定函式對任意一項return
的值為true,則返回true
,否則false
10、歸併方法
reduce()
:從前到後遍歷reduceRight()
:從後到前遍歷
都接收4個引數:前一個值
,當前值
,項的索引
,陣列物件
。每次return
的值會傳遞到下一次處理的第一個引數中。
11、ES6+ 陣列方法
參考:
- 《JavaScript高階程式設計》
- ECMAScript入門 | 阮一峰
- JavaScript入門 | 阮一峰
- mdn