# 數組
## 數組遍歷與屬性
雖然在 JavaScript 中數組是對象,但是沒有好的理由去使用 [`for in` 循環](#object.forinloop) 遍歷數組。 相反,有一些好的理由**不去**使用 `for in` 遍歷數組。
**注意:** JavaScript 中數組**不是** _關聯數組_。 JavaScript 中只有[對象](#object.general) 來管理鍵值的對應關系。但是關聯數組是**保持**順序的,而對象**不是**。
由于 `for in` 循環會枚舉原型鏈上的所有屬性,唯一過濾這些屬性的方式是使用 [`hasOwnProperty`](#object.hasownproperty) 函數, 因此會比普通的 `for` 循環慢上好多倍。
### 遍歷
為了達到遍歷數組的最佳性能,推薦使用經典的 `for` 循環。
```
var list = [1, 2, 3, 4, 5, ...... 100000000];
for(var i = 0, l = list.length; i < l; i++) {
console.log(list[i]);
}
```
上面代碼有一個處理,就是通過 `l = list.length` 來緩存數組的長度。
雖然 `length` 是數組的一個屬性,但是在每次循環中訪問它還是有性能開銷。 **可能**最新的 JavaScript 引擎在這點上做了優化,但是我們沒法保證自己的代碼是否運行在這些最近的引擎之上。
實際上,不使用緩存數組長度的方式比緩存版本要慢很多。
### `length` 屬性
`length` 屬性的 _getter_ 方式會簡單的返回數組的長度,而 _setter_ 方式會**截斷**數組。
```
var foo = [1, 2, 3, 4, 5, 6];
foo.length = 3;
foo; // [1, 2, 3]
foo.length = 6;
foo; // [1, 2, 3]
```
**譯者注:** 在 Firebug 中查看此時 `foo` 的值是: `[1, 2, 3, undefined, undefined, undefined]` 但是這個結果并不準確,如果你在 Chrome 的控制臺查看 `foo` 的結果,你會發現是這樣的: `[1, 2, 3]` 因為在 JavaScript 中 `undefined` 是一個變量,注意是變量不是關鍵字,因此上面兩個結果的意義是完全不相同的。
```
// 譯者注:為了驗證,我們來執行下面代碼,看序號 5 是否存在于 foo 中。
5 in foo; // 不管在 Firebug 或者 Chrome 都返回 false
foo[5] = undefined;
5 in foo; // 不管在 Firebug 或者 Chrome 都返回 true
```
為 `length` 設置一個更小的值會截斷數組,但是增大 `length` 屬性值不會對數組產生影響。
### 結論
為了更好的性能,推薦使用普通的 `for` 循環并緩存數組的 `length` 屬性。 使用 `for in` 遍歷數組被認為是不好的代碼習慣并傾向于產生錯誤和導致性能問題。
## `Array` 構造函數
由于 `Array` 的構造函數在如何處理參數時有點模棱兩可,因此總是推薦使用數組的字面語法 - `[]` - 來創建數組。
```
[1, 2, 3]; // 結果: [1, 2, 3]
new Array(1, 2, 3); // 結果: [1, 2, 3]
[3]; // 結果: [3]
new Array(3); // 結果: []
new Array('3') // 結果: ['3']
// 譯者注:因此下面的代碼將會使人很迷惑
new Array(3, 4, 5); // 結果: [3, 4, 5]
new Array(3) // 結果: [],此數組長度為 3
```
**譯者注:**這里的模棱兩可指的是數組的[兩種構造函數語法](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array)
由于只有一個參數傳遞到構造函數中(譯者注:指的是 `new Array(3);` 這種調用方式),并且這個參數是數字,構造函數會返回一個 `length` 屬性被設置為此參數的空數組。 需要特別注意的是,此時只有 `length` 屬性被設置,真正的數組并沒有生成。
**譯者注:**在 Firebug 中,你會看到 `[undefined, undefined, undefined]`,這其實是不對的。在上一節有詳細的分析。
```
var arr = new Array(3);
arr[1]; // undefined
1 in arr; // false, 數組還沒有生成
```
這種優先于設置數組長度屬性的做法只在少數幾種情況下有用,比如需要循環字符串,可以避免 `for` 循環的麻煩。
```
new Array(count + 1).join(stringToRepeat);
```
**譯者注:** `new Array(3).join('#')` 將會返回 `##`
### 結論
應該盡量避免使用數組構造函數創建新數組。推薦使用數組的字面語法。它們更加短小和簡潔,因此增加了代碼的可讀性。