前言:這篇文章用于了解總結JS里的數組的相關知識。我會從基本概念,構造方法和常用的API這幾個方面來介紹數組。部分概念與代碼摘自阮一峰JS教程。
1、數組是什么
數組(array)是按次序排列的一組值。每個值的位置都有編號(從0開始),整個數組用方括號表示。
其實本質上,數組屬于一種特殊的對象。typeof運算符會返回數組的類型是object。
數組的特殊性體現在,它的鍵名是按次序排列的一組整數(0,1,2…)。而由于數組成員的鍵名是固定的(默認總是0、1、2…),因此數組不用為每個元素指定鍵名,而對象的每個成員都必須指定鍵名。
2、數組的length屬性
數組的length屬性,返回數組的成員數量。只要是數組,就一定有length屬性。該屬性是一個動態的值,等于鍵名中的最大整數加上1。
3、數組的構造方法
var x = new Array(3) ; // 3表示數組的長度,每一項都為undefined
var y = new Array(3,3); // 此時得到一個數組[3,3] ,即里面的兩個參數表示數組的第0項和第1項
上面兩行代碼展示了JS的不一致行,即不同的參數個數,導致相同位置的參數所表示的意義是不同的。
使用new Array()
的構造方法,是仿自Java中的寫法,不常用。
因此,其實眾所周知的函數構造方法是直接定義,如:
var a = [3,3] ; // 得到了一個數組a,其中第0項和第一項分別為3、3
4、in 運算符 && for…in 循環
檢查某個鍵名是否存在的運算符in,適用于對象,也適用于數組。
因此,數組也是可以使用for in循環的,for...in循環不僅可以遍歷對象,也可以遍歷數組,畢竟數組只是一種特殊對象。
如:
var a = [1, 2, 3];
for (var i in a) {
console.log(a[i]);
}
// 1
// 2
// 3
但是,for...in不僅會遍歷數組所有的數字鍵,還會遍歷非數字鍵。因此不建議使用。
var a = [1, 2, 3];
a.foo = true;
for (var key in a) {
console.log(key);
}
// 0
// 1
// 2
// foo
5、數組的遍歷
上面講了使用for…in來遍歷數組,但是不建議使用,我們常用的數組遍歷方法有for循環或while循環。
如:
var a = [1, 2, 3];
// for循環
for(var i = 0; i < a.length; i++) {
console.log(a[i]);
}
// while循環
var i = 0;
while (i < a.length) {
console.log(a[i]);
i++;
}
var l = a.length;
while (l--) {
console.log(a[l]);
}
6、數組的空位
當數組的某個位置是空元素,即兩個逗號之間沒有任何值,我們稱該數組存在空位(hole),下面代碼表明,數組的空位不影響length屬性。
如:var a = [1, , 1]; a.length // 3
數組的空位是可以讀取的,返回undefined。
使用delete命令刪除一個數組成員,會形成空位,并且不會影響length屬性。如:
var a = [1, 2, 3];
delete a[1];
a[1] // undefined
a.length // 3
注:數組的某個位置是空位,與某個位置是undefined,是不一樣的。如果是空位,使用數組的forEach方法、for...in結構、以及Object.keys方法進行遍歷,空位都會被跳過,如果某個位置是undefined,遍歷的時候就不會被跳過。
如:
// 數組中有空位時
var a = [, , ,];
a.forEach(function (x, i) {
console.log(i + '. ' + x);
})
// 不產生任何輸出
for (var i in a) {
console.log(i);
}
// 不產生任何輸出
Object.keys(a)
// []
//數組中的值為undefined時
var a = [undefined, undefined, undefined];
a.forEach(function (x, i) {
console.log(i + '. ' + x);
});
// 0. undefined
// 1. undefined
// 2. undefined
for (var i in a) {
console.log(i);
}
// 0
// 1
// 2
Object.keys(a)
// ['0', '1', '2']
這就是說,空位就是數組沒有這個元素,所以不會被遍歷到,而undefined則表示數組有這個元素,值是undefined,所以遍歷不會跳過。
7、類數組對象
如果一個對象的所有鍵名都是正整數或零,并且有length屬性,那么這個對象就很像數組,語法上稱為“類似數組的對象”(array-like object)。
典型的“類似數組的對象”是函數的arguments
對象,以及大多數 DOM 元素集,還有字符串。
數組與類數組對象最本質的區別為:類數組對象的原型鏈中沒有Array.prototype
,即:
數組.__proto__ === Array.protype
類數組對象.__proto__ === Object.prototype
因此產生了一句很神奇的話:數組之所以是數組不是因為它本身是數組,而是因為你認為它是數組所以它才是數組。
8、數組的各種API
-
forEach()
遍歷
不支持break
和continue
代碼示例:
array = ['a','b','c','d'] ;
array.forEach(function(value,key){
console.log(key+':'+value);
})
// 0:a
// 1:b
// 2:c
// 3:d
其中:使用forEach
循環遍歷,原數組不會被改變,沒有返回值
-
sort()
排序
該方法是JS封裝的一個重排序方法,使用的算法是“快速排序”。不傳參時默認為升序排列。注:sort()
方法返回的是原數組,即使用該方法會改變原來的數組序列。
=>arr.sort(function(a,b){return a-b})
升序
=>arr.sort(function(a,b){return b-a})
降序
上面兩行代碼中,為什么return a-b
會升序排列,return b-a
會降序排列呢?
原理如下:
函數返回值 小于等于 -1 時,a在前,b在后
函數返回值 在區間(-1,1)時,序列不變
函數的返回值 大于等于 1 時 ,b在前,a在后
-
join()
分隔
該方法返回的是字符串,參數表示用什么分隔數組的每一項,不傳參默認逗號分隔,參數為空數組時,數組每一項之間沒有間隔。
代碼示例:
array = ["a", "b", "c", "d"];
array.join('-');
// "a-b-c-d"
-
concat()
連接
該方法返回的是新數組,原數組不會被改變。
代碼示例:
a = [1,2,30] ;
b = [42,22,33];
a.concat(b);
// 得到新數組 [1, 2, 30, 42, 22, 33]
使用concat()
方法可以用于復制數組,如:
arr = [1,2,3,4,5,6];
var newArr = arr.concat([]);
// newArr 的值為 [1, 2, 3, 4, 5, 6]
newArr === arr; // false
注:關于newArr === arr
返回的是false,因為數組也是對象,所以參照對象的相等可得,newArr 和 arr 是兩個不同地址的引用,只是恰好他們引用的地址中的值是一樣的而已,而兩個對象本身的值肯定是不同的。
-
map()
功能與forEach相同,但map()
有返回值。同樣不會改變原數組的值,返回的一個新數組。
代碼示例:
arr = [1, 2, 3, 4, 5, 6];
arr.map(function(value,key){
return value * 2;
})
// [2, 4, 6, 8, 10, 12]
-
filter()
過濾、篩選
用法與map()
一樣,代碼示例:
arr = [1, 2, 3, 4, 5, 6];
arr.filter(function(value,key){
return value > 3
})
// [4, 5, 6]
-
reduce()
可接收一個函數作為累加器
代碼示例:計算數組中每一項相加的值
arr = [1, 2, 3, 4, 5, 6];
arr.reduce(function(previous,current){
return previous + current;
},0)
// 21
即reduce()
方法,第一個參數傳一個函數作為累加器,第二個參數表示初始值。
可以用reduce()
方法來寫map()
數組每一項×2:
a = [1, 2, 3, 4, 5, 6];
a.reduce(function(array,n){
array.push(n * 2);
return array;
},[])
// [2, 4, 6, 8, 10, 12]
可以用reduce()
方法來寫filter()
篩選偶數:
a = [1, 2, 3, 4, 5, 6];
a.reduce(function(array,n){
if(n % 2 === 0){
array.push(n);
}
return array;
},[])
// [2, 4, 6]