---
# System prepended metadata

title: Javascript Sparse Array

---

在 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. 稀疏數組在創建和訪問元素方面性能表現並不好

