JavaScript里的數組詳解

前言:這篇文章用于了解總結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() 遍歷
    不支持breakcontinue
    代碼示例:
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]
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容