JavaScript:陣列
1、建立陣列
// 推薦使用
var arr = [1, ,2 ,3];
// 不推薦使用
var arr = new Array(1, 2);
2、陣列的本質
本質上,陣列屬於一種特殊的物件。
typeof[1, 2, 3] // "Object"
陣列的特殊性體現在,它的鍵名是按次序排列的一組整數(0,1,2...)。
var arr = [1, 2, 3];
Object.keys(arr) // ["0", "1", "2"]
3、陣列的遍歷
var arr = [1, 2, 3]; a.foo = true; // for...in for (var i in arr) { console.log(arr[i]); // 1 2 3 true } // for迴圈 for (var i = 0; i < arr.length; i++) { console.log(arr[i]); // 1 2 3 } // while迴圈 var i = 0; while(i < a.length) { console.log(arr[i]); // 1 2 3 i++; } // forEach arr.forEach(function (i) { console.log(i); // 1 2 3 });
使用for...in
不僅會遍歷陣列所有的數字鍵,還會遍歷非數字鍵。所以,不推薦使用for...in
遍歷陣列。
4、類似陣列的物件
如果一個物件的所有鍵名都是正整數或零,並且有length
屬性,那麼這個物件就很像陣列,語法上稱為“類似陣列的物件”(array-like object)。
-
arguments物件
function args() { return arguments } var arrayLike = args('a', 'b'); arrayLike[0] // 'a' arrayLike.length // 2 arrayLike instanceof Array // false
-
DOM元素集
var elts = document.getElementsByTagName('h3'); elts.length // 3 elts instanceof Array // false
-
字串
'abc'[1] // 'b' 'abc'.length // 3 'abc' instanceof Array // false
5、建構函式
// 無引數時,返回一個空陣列 new Array() // [] // 單個正整數引數,表示返回的新陣列的長度 new Array(1) // [ empty ] new Array(2) // [ empty x 2 ] // 非正整數的數值作為引數,會報錯 new Array(3.2) // RangeError: Invalid array length new Array(-3) // RangeError: Invalid array length // 單個非數值(比如字串、布林值、物件等)作為引數, // 則該引數是返回的新陣列的成員 new Array('abc') // ['abc'] new Array([1]) // [Array[1]] // 多引數時,所有引數都是返回的新陣列的成員 new Array(1, 2) // [1, 2] new Array('a', 'b', 'c') // ['a', 'b', 'c']
注意,如果引數是一個正整數,返回陣列的成員都是空位。雖然讀取的時候返回undefined
,但實際上該位置沒有任何值。雖然這時可以讀取到length
屬性,但是取不到鍵名。
var a = new Array(3);
var b = [undefined, undefined, undefined];
a.length // 3
b.length // 3
a[0] // undefined
b[0] // undefined
0 in a // false
0 in b // true
6、方法
-
Array.isArray()
:用來判斷某個變數是否是一個數組物件。var arr = [1, 2, 3]; typeof arr // "object" Array.isArray(arr) // true
-
valueOf()
:返回陣列本身。Array.valueOf === Object.prototype.valueOf // true var arr = [1, 2, 3]; arr.valueOf() // [1, 2, 3]
-
toString()
:返回陣列的字串形式。Array.toString === Function.prototype.toString // true var arr = [1, 2, 3]; arr.toString() // "1,2,3" var arr = [1, 2, 3, [4, 5, 6]]; arr.toString() // "1,2,3,4,5,6"
-
push()
:在陣列的末端新增一個或多個元素,並返回新增新元素後的陣列長度。注意,該方法會改變原陣列。var arr = []; arr.push(1) // 1 arr.push('a') // 2 arr.push(true, {}) // 4 arr // [1, 'a', true, {}]
-
pop()
:刪除陣列的最後一個元素,並返回該元素。注意,該方法會改變原陣列。var arr = ['a', 'b', 'c']; arr.pop() // 'c' arr // ['a', 'b'] [].pop() // undefined
-
shift()
:刪除陣列的第一個元素,並返回該元素。注意,該方法會改變原陣列。var a = ['a', 'b', 'c']; a.shift() // 'a' a // ['b', 'c'] // 使用shift()遍歷陣列 var arr = [1, 2, 3, 4]; var i; while(i = arr.shift()) { console.log(i); // 1 2 3 4 } arr // []
-
unshift()
:在陣列的第一個位置新增元素,並返回新增新元素後的陣列長度。注意,該方法會改變原陣列。var a = ['a', 'b', 'c']; a.unshift('x'); // 4 a // ['x', 'a', 'b', 'c']
-
join()
:以指定引數作為分隔符,將所有陣列成員連線為一個字串返回。如果不提供引數,預設用逗號分隔。var a = [1, 2, 3, 4]; a.join(' ') // '1 2 3 4' a.join(' | ') // "1 | 2 | 3 | 4" a.join() // "1,2,3,4" // 如果陣列成員是undefined或null或空位,會被轉成空字串。 [undefined, null].join('#') // '#' ['a',, 'b'].join('-') // 'a--b'
-
concat()
:用於多個數組的合併。它將新陣列的成員,新增到原陣列成員的後部,然後返回一個新陣列,原陣列不變。['hello'].concat(['world']) // ["hello", "world"] [1, 2, 3].concat(4, 5, 6) // [1, 2, 3, 4, 5, 6]
如果陣列成員包括物件,
concat
方法返回當前陣列的一個淺拷貝。所謂“淺拷貝”,指的是新陣列拷貝的是物件的引用。var obj = { a: 1 }; var oldArray = [obj]; var newArray = oldArray.concat(); obj.a = 2; newArray[0].a // 2
-
reverse()
:用於顛倒排列陣列元素,返回改變後的陣列。注意,該方法將改變原陣列。var a = ['a', 'b', 'c']; a.reverse() // ["c", "b", "a"] a // ["c", "b", "a"]
-
slice()
:用於提取目標陣列的一部分,返回一個新陣列,原陣列不變。arr.slice([begin[, end]]) var a = ['a', 'b', 'c']; // 如果省略第二個引數,則一直返回到原陣列的最後一個成員。 a.slice(0) // ["a", "b", "c"] a.slice(1) // ["b", "c"] // 包前不包後 a.slice(1, 2) // ["b"] a.slice(2, 6) // ["c"] // 如果沒有引數,則返回原陣列的拷貝。 a.slice() // ["a", "b", "c"] // 如果slice()方法的引數是負數,則表示倒數計算的位置。 var a = ['a', 'b', 'c']; a.slice(-2) // ["b", "c"] a.slice(-2, -1) // ["b"] // 如果第一個引數大於等於陣列長度,或者第二個引數小於第一個引數,則返回空陣列。 var a = ['a', 'b', 'c']; a.slice(4) // [] a.slice(2, 1) // []
slice()
方法的一個重要應用,是將類似陣列的物件轉為真正的陣列。Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 }) // ['a', 'b'] Array.prototype.slice.call(document.querySelectorAll("div")); Array.prototype.slice.call(arguments);
-
splice()
:用於刪除原陣列的一部分成員,並可以在刪除的位置新增新的陣列成員,返回值是被刪除的元素。注意,該方法會改變原陣列。array.splice(start[, deleteCount[, item1[, item2[, ...]]]]) var a = ['a', 'b', 'c', 'd', 'e', 'f']; a.splice(4, 2, 1, 2) // ["e", "f"] a // ["a", "b", "c", "d", 1, 2] // 如果只提供第一個引數,等同於將原陣列在指定位置拆分成兩個陣列。 var a = [1, 2, 3, 4]; a.splice(2) // [3, 4] a // [1, 2]
-
sort()
:對陣列成員進行排序,預設是按照字典順序排序。排序後,原陣列將被改變。['d', 'c', 'b', 'a'].sort() // ['a', 'b', 'c', 'd'] [4, 3, 2, 1].sort() // [1, 2, 3, 4] [11, 101].sort() // [101, 11] [10111, 1101, 111].sort() // [10111, 1101, 111] // 如果想讓sort方法按照自定義方式排序,可以傳入一個函式作為引數。 [10111, 1101, 111].sort(function (a, b) { return a - b; }) // [111, 1101, 10111]
注意,自定義的排序函式應該返回數值,否則不同的瀏覽器可能有不同的實現,不能保證結果都一致。
// bad [1, 4, 2, 6, 0, 6, 2, 6].sort((a, b) => a > b) // good [1, 4, 2, 6, 0, 6, 2, 6].sort((a, b) => a - b)
-
map()
:將陣列的所有成員依次傳入引數函式,然後把每一次的執行結果組成一個新陣列返回。var new_array = arr.map(function callback(currentValue[, index[, array]]) { // Return element for new_array }[, thisArg]) // 回撥函式有三個引數,currentValue為當前成員的值,index為當前成員的位置,array為原陣列 // thisArg用來繫結回撥函式內部的this變數
-
forEach()
:對陣列的每個元素執行一次給定的函式,沒有返回值。arr.forEach(function callback(currentValue [, index [, array]])[, thisArg]) // forEach()的引數與map()相同 // forEach()不會跳過undefined和null,但會跳過空位。
-
filter()
:用於過濾陣列成員,滿足條件的成員組成一個新陣列返回。var newArray = arr.filter(function callback(element[, index[, array]])[, thisArg]) // 回撥函式有三個引數,element為當前成員,index為當前成員的位置,array為原陣列 // thisArg用來繫結回撥函式內部的this變數
-
some()
:只要一個成員的返回值是true
,則整個some
方法的返回值就是true
,否則返回false
。arr.some(function callback(element[, index[, array]])[, thisArg]) // 回撥函式有三個引數,element為當前成員,index為當前成員的位置,array為原陣列 // thisArg用來繫結回撥函式內部的this變數
-
every()
:所有成員的返回值都是true
,整個every
方法才返回true
,否則返回false
。arr.every(function callback(element[, index[, array]])[, thisArg]) // 回撥函式有三個引數,element為當前成員,index為當前成員的位置,array為原陣列 // thisArg用來繫結回撥函式內部的this變數
-
reduce()
:從左到右依次處理陣列的每個成員,最終累計為一個值。arr.reduce(function callback(accumulator, currentValue[, index[, array]])[, initialValue]) // accumulator累積變數,currentValue當前變數,index當前位置,array原陣列,initialValue累積變數初始值 // 找出字元長度最長的陣列成員。 function findLongest(entries) { return entries.reduce(function (longest, entry) { return entry.length > longest.length ? entry : longest; }, ''); } findLongest(['aaa', 'bb', 'c']) // "aaa"
-
reduceRight()
:從右到左依次處理陣列的每個成員,最終累計為一個值。arr.reduceRight(function callback(accumulator, currentValue[, index[, array]])[, initialValue]) // accumulator累積變數,currentValue當前變數,index當前位置,array原陣列,initialValue累積變數初始值 // 在空陣列上呼叫 reduce 或 reduceRight 且未提供初始值會導致型別錯誤
-
indexOf()
:返回給定元素在陣列中第一次出現的位置,如果沒有出現則返回-1
。arr.indexOf(searchElement[, fromIndex]) // searchElement要查詢的元素,fromIndex開始查詢的位置 [NaN].indexOf(NaN) // -1
-
lastIndexOf()
:返回給定元素在陣列中最後一次出現的位置,如果沒有出現則返回-1
。arr.lastIndexOf(searchElement[, fromIndex]) // searchElement要查詢的元素,fromIndex開始查詢的位置 [NaN].lastIndexOf(NaN) // -1
-
鏈式使用:上面這些陣列方法之中,有不少返回的還是陣列,所以可以鏈式使用。
var users = [ {name: 'tom', email: '[email protected]'}, {name: 'peter', email: '[email protected]'} ]; users .map(function (user) { return user.email; }) .filter(function (email) { return /^t/.test(email); }) .forEach(function (email) { console.log(email); }); // "[email protected]"
上面程式碼中,先產生一個所有 Email 地址組成的陣列,然後再過濾出以
t
開頭的 Email 地址,最後將它打印出來。