JavaScript 數(shù)組

2021-09-15 15:12 更新

數(shù)組的定義

數(shù)組(array)是按次序排列的一組值,單個(gè)值稱為元素,它們的位置都有編號(從0開始)。整個(gè)數(shù)組用方括號表示。

var arr = ['a', 'b', 'c'];

上面代碼中的a、b、c就構(gòu)成一個(gè)數(shù)組,兩端的方括號是數(shù)組的標(biāo)志,a是0號位置,b是1號位置,c是2號位置。

除了在定義時(shí)賦值,數(shù)組也可以先定義后賦值。

var arr = [];

arr[0] = 'a';
arr[1] = 'b';
arr[2] = 'c';

任意一種類型的數(shù)據(jù),都可以放入數(shù)組。

var arr = [{a:1}, [1,2,3],function (){return true;}];

arr[0] // Object {a: 1}
arr[1] // [1, 2, 3]
arr[2] // function (){return true;}

上面數(shù)組的3個(gè)成員分別是對象、數(shù)組、函數(shù)。

如果數(shù)組的元素還是數(shù)組,就形成了多維數(shù)組。

var a = [[1,2],[3,4]];
a[0][1] // 2
a[1][1] // 4

數(shù)組與對象的關(guān)系

本質(zhì)上,數(shù)組也屬于對象,是字典結(jié)構(gòu)(dictionary)的一個(gè)變種。

typeof [1,2,3] // "object"

上面代碼表明,數(shù)組只是一種特殊的對象,所以typeof運(yùn)算符返回?cái)?shù)組的類型是object。

數(shù)組的特殊性體現(xiàn)在,它的鍵默認(rèn)是按次序排列的整數(shù)(0,1,2...),所以數(shù)組不用為每個(gè)元素指定鍵名,而對象的每個(gè)成員都必須指定鍵名。此外,對象以字符串來識別鍵名,非字符串的鍵名會被轉(zhuǎn)為字符串,所以使用數(shù)值或字符串作為鍵名,都能讀取數(shù)組的成員。

var arr = ['a', 'b', 'c'];

arr['0'] // 'a'
arr[0] // 'a'

上面代碼分別用數(shù)值和字符串作為鍵名,結(jié)果都能讀取數(shù)組。

需要注意的是,這一條在賦值時(shí)也成立,即如果一個(gè)值可以被轉(zhuǎn)換為整數(shù),則以該值為鍵名,等于以對應(yīng)的整數(shù)為鍵名。

var a = [];

a['1000'] = 'abc';
a[1000] // 'abc'

a[1.00] = 6;
a[1] // 1

上面代碼表明,由于字符串“1000”和浮點(diǎn)數(shù)1.00都可以轉(zhuǎn)換為整數(shù),則視同為整數(shù)鍵賦值。

上一節(jié)說過,對象有兩種讀取成員的方法:“點(diǎn)”結(jié)構(gòu)(object.key)和方括號結(jié)構(gòu)(object[key])。但是,對于數(shù)字的鍵名,不能使用點(diǎn)結(jié)構(gòu),arr.0的寫法不合法,因?yàn)閱为?dú)的數(shù)字不能作為標(biāo)識符(identifier)。所以,數(shù)組成員只能用方括號arr[0]表示(方括號是運(yùn)算符,可以接受數(shù)值)。

length屬性

數(shù)組的length屬性,返回?cái)?shù)組的成員數(shù)量。

['a', 'b', 'c'].length // 3

JavaScript使用一個(gè)32位整數(shù),保存數(shù)組的元素個(gè)數(shù)。這意味著,數(shù)組成員最多只有4294967295個(gè)(232-1)個(gè),也就是說length屬性的最大值就是4294967295。

數(shù)組的length屬性與對象的length屬性有區(qū)別,只要是數(shù)組,就一定有l(wèi)ength屬性,而對象不一定有。而且,數(shù)組的length屬性是一個(gè)動態(tài)的值,等于鍵名中的最大整數(shù)加上1。

var arr = ['a', 'b'];
arr.length // 2

arr[2] = 'c';
arr.length // 3

arr[9] = 'd';
arr.length // 10

arr[1000] = 'e';
arr.length // 1001

上面代碼表示,數(shù)組的數(shù)字鍵不需要連續(xù),length屬性的值總是比最大的那個(gè)整數(shù)鍵大1。另外,這也表明數(shù)組是一種動態(tài)的數(shù)據(jù)結(jié)構(gòu),可以隨時(shí)增減數(shù)組的成員。

length屬性是可寫的。如果人為設(shè)置一個(gè)小于當(dāng)前成員個(gè)數(shù)的值,該數(shù)組的成員會自動減少到length設(shè)置的值。

var arr = [ 'a', 'b', 'c' ];
arr.length // 3

arr.length = 2;
arr // ["a", "b"]

上面代碼表示,當(dāng)數(shù)組的length屬性設(shè)為2,即最大的整數(shù)鍵只能是1,那么整數(shù)鍵2(值為c)就已經(jīng)不在數(shù)組中了,被自動刪除了。

將數(shù)組清空的一個(gè)有效方法,就是將length屬性設(shè)為0。

var arr = [ 'a', 'b', 'c' ];

arr.length = 0;
arr // []

如果人為設(shè)置length大于當(dāng)前元素個(gè)數(shù),則數(shù)組的成員數(shù)量會增加到這個(gè)值,新增的位置填入空元素。

var a = ['a'];

a.length = 3;
a // ["a", undefined × 2]

上面代碼表示,當(dāng)length屬性設(shè)為大于數(shù)組個(gè)數(shù)時(shí),新增的位置都填充為undefined。

如果人為設(shè)置length為不合法的值,JavaScript會報(bào)錯(cuò)。

// 設(shè)置負(fù)值
[].length = -1
// RangeError: Invalid array length

// 數(shù)組元素個(gè)數(shù)大于等于2的32次方
[].length = Math.pow(2,32)
// RangeError: Invalid array length

// 設(shè)置字符串
[].length = 'abc'
// RangeError: Invalid array length

值得注意的是,由于數(shù)組本質(zhì)上是對象的一種,所以我們可以為數(shù)組添加屬性,但是這不影響length屬性的值。

var a = [];

a["p"] = "abc";
a.length // 0

a[2.1] = "abc";
a.length // 0

上面代碼將數(shù)組的鍵分別設(shè)為字符串和小數(shù),結(jié)果都不影響length屬性。因?yàn)?,length屬性的值就是等于最大的數(shù)字鍵加1,而這個(gè)數(shù)組沒有整數(shù)鍵,所以length屬性保持為0。

數(shù)組的空位

當(dāng)數(shù)組的某個(gè)位置是空元素(比如兩個(gè)逗號之間沒有任何值,或者值為undefined),我們稱該數(shù)組存在空位(hole)。

var a = [1,,1];
a // [1, undefined, 1]
a.length // 3

需要注意的是,如果最后一個(gè)元素后面有逗號,并不會產(chǎn)生空位。也就是說,有沒有這個(gè)逗號,結(jié)果都是一樣的。不過,IE 8及以下版本不支持這條語法規(guī)則,會報(bào)錯(cuò)。

var a = [1,2,3,];

a.length // 3
a // [1, 2, 3]

上面代碼中,數(shù)組最后一個(gè)成員后面有一個(gè)逗號,這不影響length屬性的值,與沒有這個(gè)逗號時(shí)效果一樣。

使用delete命令刪除一個(gè)值,會形成空位。

var a = [1,2,3];

delete a[1];
a // [1, undefined, 3]

需要注意的是,如果使用delete命令刪除一個(gè)值,不影響length屬性。

var a = [1,2,3];
delete a[1];
delete a[2];
a // [1, undefined, undefined]
a.length // 3

上面代碼用delete命令刪除了兩個(gè)鍵,對length屬性沒有影響。因?yàn)檫@兩個(gè)鍵還在,只是值變?yōu)榱藆ndefined。也就是說,length屬性不過濾undefined的值。所以,使用length屬性進(jìn)行數(shù)組遍歷,一定要非常小心。

空位通過空值生成,還是通過顯式設(shè)為undefined生成,有一個(gè)細(xì)微的差別。如果通過空值生成,使用數(shù)組的forEach方法或者for...in結(jié)構(gòu)進(jìn)行遍歷,空位就會被跳過。

var a = [,,,];

a.forEach(function (x, i) { console.log(i+". "+x) })
// 不產(chǎn)生任何輸出 

for (var i in a){console.log(i)}
// 不產(chǎn)生任何輸出

如果空位是通過顯式定義undefined生成,遍歷的時(shí)候就不會被跳過。

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

in運(yùn)算符,for...in循環(huán)

檢查某個(gè)鍵是否存在的運(yùn)算符in,適用于對象,也適用于數(shù)組。

2 in [ 'a', 'b', 'c' ]
// true

'2' in [ 'a', 'b', 'c' ]
// true

使用for-in循環(huán),可以遍歷數(shù)組的所有元素。

var a = [1,2,3];

for (var i in a){
    console.log(a[i]);
}
// 1
// 2
// 3

需要注意的是,for-in會遍歷數(shù)組所有的鍵,即使是非數(shù)字鍵。

var a = [1,2,3];
a.foo = true;

for (var key in a) { 
    console.log(key); 
}
// 0
// 1
// 2
// foo

上面代碼在遍歷數(shù)組時(shí),也遍歷到了非整數(shù)鍵foo。所以,使用for-in遍歷數(shù)組的時(shí)候,一定要小心。

另一種遍歷的做法是用for循環(huán)或者while循環(huán)結(jié)合length屬性。

var a = [1,2,3];
for(var i = 0; i < a.length; i++){
    console.log(a[i]);
}

// or

var i = 0;
while (i< a.length){
    console.log(a[i]);
    i++;
}

// or

var l = a.length;
while (l--){
    console.log(a[l]);
}

上面代碼是三種遍歷數(shù)組的寫法。最后一種寫法是逆向遍歷,即從最后一個(gè)元素向第一個(gè)元素遍歷。

Array構(gòu)造函數(shù)

除了直接使用方括號創(chuàng)建,數(shù)組還可以使用JavaScript內(nèi)置的Array構(gòu)造函數(shù)創(chuàng)建。

var a = new Array();
a // []
a.length // 0

var a = new Array(1);
a // [undefined × 1]
a.length // 1

var a = new Array(2);
a // [undefined × 2]
a.length // 2

var a = new Array(1,2);
a // [1,2]
a.length // 2

上面代碼說明,Array構(gòu)造函數(shù)的用法不符合直覺。沒有參數(shù)時(shí),返回一個(gè)空數(shù)組;使用一個(gè)參數(shù)時(shí),返回一個(gè)指定長度的空數(shù)組;使用多個(gè)參數(shù),返回一個(gè)指定成員的數(shù)組。所以,建議總是直接采用方括號創(chuàng)建數(shù)組。Array構(gòu)造函數(shù)的詳細(xì)介紹,參見《標(biāo)準(zhǔn)庫》一章的《Array對象》。

參考鏈接

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號