JavaScript 數組
數組是一種使用整數作為鍵 (integer-key-ed) 屬性和長度 (length) 屬性之間關聯的常規對象。此外,數組對象還繼承了 Array.prototype 的一些操作數組的便捷方法?!狹DN
數組可以存放多個值。數組的數
不是指數字,而是指數據
,數組可以存放任意數據類型的值。
從理論上講,在內存允許的情況下,數組的長度是無限的。
1. 創建數組
數組由中括號 []
包裹,每一項之間用逗號 ,
分隔。
[第一項, 第二項, 第三項, ... , 第n項]
創建數組最常見的方式是使用字面量。
var hobby = ['java', 'c', 'c++', 'python', 'javascript', 1, 2, 3, true, false];
console.log(hobby);
通過直接描述一個數組的方式就可以創建一個數組。
2. 數組長度
數組的長度可以通過 length
屬性獲取。
var arr = [1, 2, 3, 4, 5];
console.log(arr.length); // 5
3. 訪問數組成員
數組的每一項可以稱之為成員
。
數組成員可以通過下標
訪問,下標也可以稱為索引
。
下標可以理解成數組成員的編號,編號從 0 開始,到數組長度 -1 。
var arr = ['第一項', '第二項', '第三項'];
var item1 = arr[0]; // 從0開始編號 第一項的下標是0
var item2 = arr[1];
var item3 = arr[2];
console.log(item1); // 輸出:第一項
console.log(item2); // 輸出:第二項
console.log(item3); // 輸出:第三項
通過數組[下標]
的方式即可訪問到成員。
4. 遍歷數組
數組遍歷主要有兩種方式:
- for 循環
- forEach 方法
4.1 for 循環
使用 for 循環,從數組下標 0 循環到最后一位,過程中通過下標訪問成員。
var arr = ['第一項', '第二項', '第三項', '第四項', '第五項'];
var i, len;
for (i = 0, len = arr.length - 1; i <= len; i++) {
console.log(arr[i]);
}
4.2 forEach 方法
forEach
是數組原型上的方法,所有數組都具有此方法。
forEach 接收一個函數作為參數,在遍歷每一項的時候,這個函數會被調用,同時將當前遍歷到的項、當前項的下標(索引)、遍歷的數組作為函數參數傳遞過來。
var arr = ['第一項', '第二項', '第三項', '第四項', '第五項'];
arr.forEach(function(item, index, arr) {
console.log('第' + (index + 1) + '項的值是:' + item);
});
第二個參數的值也是從 0 開始的。
通常第三個參數用到的比較少,沒有用到可以沒必要接收這個參數。
5. 修改數組成員的值
成員的值可以通過數組[下標] = 值
的方式進行修改。
var arr = ['一', '三', '三', '四'];
console.log(arr[1]); // 輸出:"三"
arr[1] = '二';
console.log(arr[1]); // 輸出:"二"
6. 增減數組項
數組提供了很多方式來對成員進行增減操作,也可以依靠其他特性來增加減少數組成員。
6.1 增加
6.1.1 直接給指定位置賦值
通過下標,直接訪問到一個不存在的成員,然后進行賦值,就可以為數組增加一項。
var arr = ['jquery', 'react'];
arr[1] = 'vue';
arr[2] = 'angular';
console.log(arr[2]); // 輸出:"angular"
console.log(arr.length); // 輸出:3
6.1.2 push 方法
push 方法接收任意個參數,這些參數會依次添加到數組的末尾,添加完后返回數組新的長度。
var arr = [1];
var length = arr.push(2, 3);
console.log(arr); // 輸出:[1, 2, 3]
console.log(length); // 輸出:3
通常不會用到這個返回的長度,可以不需要接收返回值。
6.1.3 unshift 方法
unshift 接收任意個參數,這些參數會被添加到數組頭部,添加完后返回數組新的長度。
var arr = [3];
var length = arr.unshift(1, 2);
console.log(arr); // 輸出:[1, 2, 3]
console.log(length); // 輸出:3
6.2 刪除
6.2.1 pop 方法
pop 方法會刪除數組最后一項,并將刪除項作為返回值。
var arr = ['c++', 'java', 'javascript'];
var lastOne = arr.pop();
console.log(lastOne); // 輸出:"javascript"
如果數組是空的,調用 pop 會返回 undefined
。
6.2.2 shift 方法
shift 方法會刪除數組的第一項,并將刪除項作為返回值。
var arr = ['996', '007'];
const first = arr.shift();
console.log(first); // 輸出:"996"
與 pop 一樣,如果是數組為空的情況下,會返回 undefined
。
6.3 在數組中間刪除或添加值
splice 方法可以在任意位置添加或刪除值。
這個方法接受任意個參數,前兩個為從哪里開始(從 0 開始計數),刪除幾個,從第三個開始則是要添加的項。
arr.splice(從第幾個開始, 要刪除幾個, 要添加的項目1, 要添加的項目2, ..., 要添加的項目n);
如果不需要刪除,只需要往數組中間插入值,只需要傳遞 0 給第二個參數即可。
// 在第二項之后插入3, 4, 5
var arr = [1, 2, 6];
arr.splice(2, 0, 3, 4, 5);
因為第一個參數是從 0 開始計數,所以在第二項之后,就是要插入在第三項的位置,所以傳遞 2 ,不需要刪除項目,所以第二個參數傳遞 0 ,之后就是要插入的項。
注意:往數組中間插入數據的情況相對較少,數組做這種操作是比較低效的,小量的操作對性能的影響可以忽略不計,但有超大量非首尾的增減操作,應考慮使用
鏈表
。
刪除項只需要指定從第幾項開始刪除,要刪除幾項即可。
// 去除 '996'、'加班'
var arr = ['早睡早起', '朝九晚五', '996', '加班'];
arr.splice(2, 2);
'996’和’加班’是連續的,所以一個 splice 就可以刪除掉這 2 項,2 個參數的意思就是從第 2 項開始,刪除 2 項。
7. 清空數組
將數組所有成員全部刪除就達到了清空的效果。
var arr = [1, 2, 3, 4];
arr.splice(0, arr.length);
當然也可以使用 pop
一個個刪除,但是通常都不會用這種方式。
清空數組最常用的方式是重新給變量賦值。
var arr = ['red', 'green', 'blur'];
arr = [];
console.log(arr); // 輸出空數組:[]
通過給變量賦值一個新的空數組,達到清空數組的目的,但是這樣會改變引用,新賦值的數組和之前的數組并不是同一個。
另一種方式可以讓保持對當前數組的引用。
var arr = ['yellow', 'black'];
arr.length = 0;
通過給數組的 length
屬性重新賦值,也可以達到清空數組的效果。
這種方式相對靈活,假如需求是保留三項、五項,只需要給 length 賦值對應的值即可。
8. 使用 Array 創建數組
內建對象 Array
也可以用來創建數組。
var arr = new Array();
如果什么參數都不傳遞,則返回一個空數組。
傳參則有 2 種情況:
- 如果只傳一個參數,并且這個參數的類型為數字,則會創建長度為這個數字的數組;
- 傳入其他類型的一個或者多個參數,則會將這些參數組合成數組。
var arr = new Array(10);
console.log(arr); // 輸出:[empty × 10]
console.log(arr.length); // 輸出:10
在控制臺可以觀察到這個數組長度為 10,但均為 empty
。
如果嘗試著訪問其中某一項,得到的值是 undefined
。
var arr1 = new Array('item1');
var arr2 = new Array(1, 2, 'item3');
console.log(arr1); // 輸出:["item1"]
console.log(arr2); // 輸出:[1, 2, "item3"]
這樣創建的數組,成員與傳參一致。
9. 數組中的 undefined 與 empty
在數組中 undefined 與 empty 是有區別的。
使數組項變成 empty
通常有兩種方式。
- 使用 Array 對象同時提供了長度創建出來的數組
- 使用
delete
關鍵字刪除的數組項
var arr1 = new Array(10);
arr1[0] = 1;
var arr2 = [1, 2, 3, 4, 5];
delete arr2[3];
console.log(arr1);
console.log(arr2);
雖然 empty 的項在訪問的時候返回的是 undefined ,但其本身只做簡單占位,\ 是遍歷不到的。
var arr = [1, undefined, 3, 4, 5];
delete arr[3];
arr.forEach(function(item, index) {
console.log(index, item);
});
var i = 0;
for (i in arr) {
console.log(i, arr[i]);
}
上面兩種遍歷的方式都是遍歷不到 empty
項的,而 undefined
是可以遍歷到的,這是最主要的區別。
10. 使用數組
數組非常常用,大量的 HTML 字符串在做拼接的時候,就會使用到數組。
除了用于簡單的存儲數據,數組也可以被用來解決問題。
10.1 判斷括號是否匹配
判斷一個數學式子的括號匹配是否合法,如 (1 + 2) * (3 + 4))
,這個式子就是不合法的。
校驗括號合法不單單要看左括號和右括號的數量是否相等,還要看括號的順序, ))((
這樣的括號順序一定是錯誤的。
利用 JavaScript 數組的特性,可以很容易的實現。
// 空數組
var stack = [];
// 一個式子
var equation = '(1 + (2 - 3) * 4) / (1 - 3)';
var i, len;
for (i = 0, len = equation.length; i < len; i++) {
if (equation[i] === '(') { // 如果碰到左括號
// 往數組里放個1
stack.push(1);
} else if (equation[i] === ')') { // 如果碰到右括號
if (!stack.length) { // 判斷數組長度,如果是0,則肯定是出錯的,數組長度0的時候說明沒有左括號,沒有左括號是不可能出現右括號的
// 隨便放一個1
stack.push(1);
break;
}
// 如果數組不是空的 就從數組末尾拿一個走。
stack.pop();
}
}
// 判斷數組長度
if (!stack.length) { // 如果數組已經空了,說明括號都一一對應,式子里的括號沒問題。
console.log('括號合法');
} else {
console.log('括號不合法');
}
使用數組實現的具體思路就是,碰到左括號就往數組里放一個成員,碰到一個右括號就拿掉一個成員。
這樣如果最后有剩下,說明括號沒有一一成對。
(1+2*(3+4))*1
如這樣一個式子:
初始化操作:
定義數組 arr為空
從式子第一個字符開始循環
第一次循環:
數組的值為 []
得到字符"("
判斷是左括號,往數組里放一個1,表示碰到了左括號
第二次循環
數組的值為 [1]
得到字符"+"
既不是左括號,又不是右括號,進行下一輪循環,不做操作
第三次循環
第四次循環
第五次循環
與第二次循環基本一致
第六次循環
數組的值為 [1]
得到字符"("
是左括號 往數組里再放一個1,表示碰到了左括號
第七次循環
數組值為 [1, 1]
得到字符"3"
不是左括號,也不是右括號,進行下一輪循環
第八次循環
第九次循環
與第七次一致
第十次循環
數組的值為 [1, 1]
得到字符")"
是右括號,從數組末尾拿掉一項
第十一次循環
數組的值為 [1]
得到字符")"
是右括號,從數組末尾拿掉一項
第十二次循環
第十三次循環
數組值為 []
都不是括號,不做操作
循環結束
判斷數組值,如果是空的,說明括號匹配完了,顯然 (1+2*(3+4))*1 是合法的
當然這種判斷有局限性,假如碰到 ((1+)2)-3
這種非括號造成不合法的式子,就判斷不出來了。
其實這里用到了
棧
這種數據結構,這個問題在棧的應用上很經典,是算法入門常見面試題之一。
11. 類數組
類數組并不是數組,而是長得像數組的對象。
var fakeArray = {
0: '第一項',
1: '第二項',
3: '第三項',
length: 3,
};
console.log(fakeArray[0]); // 輸出:"第一項"
console.log(fakeArray.length); // 輸出:3
上述例子中的 fakeArray
就是一個類數組,屬性是以類型數組的下標
的形式存在,同時也具有 length
屬性。
這種類數組對象,也被稱為 array-like對象
,部分文獻也稱為偽數組
。
類數組對象可以轉化為數組,許多方法在設計時也會考慮支持類數組。
12. 小結
JavaScript 中的數組非常靈活,可以存放任意類型、任意長度 (內存足夠的情況下) 的數據,其下標從 0 開始,最大到數組長度減去 1 ,并提供了一系列方法,來完成增、刪、改、查操作。
數組項的 empty
和 undefined
的區別,是面試中常問的問題。