在 code review 的時候,發現一段這樣的代碼:
```javascript!
const aiRatingLabels = new Array(5).fill(1).map((_, idx) => 5 - idx)
```
之前很少用這種方式去create array,印象中有都市傳說說使用 new Array() 有坑。
## Sparse Array 稀疏陣列 & Dense Array 密集陣列
Dense Array 密集陣列
```javascript
var arr = [1,3,2];
console.log(arr);
```
Sparse Array 稀疏陣列
```javascript!
var arr1 = [1,,2];
console.log(arr1);
var arr2 = new Array(5);
arr2[2] = 'apple'
console.log(arr2);
```
在JavaScript中,"array empty"指的是陣列中某個位置沒有被實際元素填充,也就是沒有存儲任何值。
"empty"元素的存在使得陣列的長度與實際元素個數可以不一致,這就是稀疏數組的特性。
稀疏陣列: 索引不連續,陣列長度大於元素個數的陣列, 可以簡單理解為有 empty 的陣列;
密集陣列: 索引連續, 陣列長度等於元素個數的陣列;
### new Array(length) 做了甚麼
1. 判斷 len 是否為合法數字(小於 2^32 - 1 的正整數),如果不是則拋出錯誤
1. 創建一個 JavaScript Array 實例
1. 將這個實例對象的 length 屬性設置為入參的值
上面的操作相當於:
```javascript
let arr = [];
arr.length = 5; //[empty × 5]
```
### array object
javascript 一切都是 object 包含, new Array(5)只是將length屬性設置為5。因此,使用new Array創建的陣列只是一個帶有length屬性 = 5 的 object,但沒有填充任何元素。
## 坑
### for loop
```javascript
const arr = [1, , 2, , 3,]
//[ 1, empty item, 2, empty item, 3 ]
for(let i = 0, len = arr.length; i < len; i++){
console.log(i)
console.log(arr[i])
}
```
### for each
```javascript!
const arr = [1, , 2, , 3,]
arr.forEach((val,idx) => {
console.log(val)
})
arr.forEach((val,idx) => {
console.log(idx)
})
```
### map
```javascript
const newArr = arr.map((val, index) => {
console.log(index)
return val * val
})
console.log(newArr)
```
### for in , for of
```javascript
const arr = [1, , 2, , 3]
for (var i in arr) { console.log(arr[i]) }
for (var i of arr) { console.log(i) }
```
### join
```javascript
const arr = [1, , 2, , 3]
console.log(arr.join(','))
```
### 訪問效能
``` javascript
const arr1 = new Array(200000)
arr1[19999] = 88
console.time('sparse array[]')
arr1[19999]
console.timeEnd('sparse array[]')
const arr2 = [...new Array(200000)]
arr2[19999] = 88
console.time('dense array[]')
arr2[19999]
console.timeEnd('dense array[]')
```
稀疏陣列在v8引擎訪問 objects 時,objects是使用 hash table存取,在訪問的時需要計算 hash 值
一般陣列 儲存在一段連續的記憶體位置上
### 稀疏陣列轉換成密集陣列
``` javascript
// ES5
var arr = new Array(5);
Array.apply(null, arr);
// ES6
Array.from(arr);
[...arr];
```
## 結論
1. 盡量避免使用稀疏陣列,或會創造出稀疏陣列的寫法
2. 稀疏陣列在一些遍歷陣列的方法都不會執行 callback,與我們預期的不太一樣,可能會踩到一些坑.
3. 稀疏數組在創建和訪問元素方面性能表現並不好