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