在 JavaScript 中建立陣列的正確姿勢

沃趣葫蘆娃發表於2019-03-03

JavaScript 中陣列的特殊性

  • 每一項都可以儲存任意型別的資料,陣列大小可以動態調整,即可以隨著資料的新增自動增長以容納新資料
  • 陣列中可能會存在空位
  • 稀疏陣列

具有不連續索引的陣列,其 length 屬性值大於元素的個數。

  • 密集陣列

具有連續索引的陣列,其 length 屬性值等於元素的個數。

在 JavaScript 中,陣列本質上也是物件,是物件的一種特殊形式。

陣列索引實際上和碰巧是整數名的物件屬性沒有什麼差別,不過陣列的實現是經過了優化的,通過陣列索引訪問陣列元素比訪問一般物件的屬性要快的多。

規定陣列索引的範圍是 0 ~ 4294967294 (2^32 - 2), 所有的索引都是屬性名, 但是隻有在這個範圍內的整數才是陣列索引,陣列索引會觸發陣列的特殊行為。

陣列的建立方式

陣列字面量

這是我們平時使用最多,最簡單的陣列建立方式。

const arr1 = []
複製程式碼

建構函式

利用建構函式建立陣列的時候,在只有一個引數的情況下,根據引數的型別不同,會返回不同的結果。

// 注:這種方式建立的陣列屬於稀疏陣列,每一項都是空位,下邊會具體介紹稀疏陣列。
// 請避免使用這樣的方式建立陣列。
const arr1 = Array(3) // [empty × 3]
const arr2 = Array(`3`) // ["3"]
複製程式碼

of() 方法

這是 ES6 中新增的方法,用來彌補建構函式的的缺陷。
不會根據引數的型別不同導致建立行為的不同。

const arr1 = Array.of(3) // [3]
const arr2 = Array.of(`3`) // [`3`]
複製程式碼

from() 方法

ES6 新增的方法,這個方法的主要用途就是將類陣列物件轉為陣列物件。
建立給定長度的陣列這個方法會很好用。

const arr1 = Array.from({length: 3}) // [undefined, undefined, undefined]
複製程式碼

稀疏陣列

稀疏陣列就是存在空位的陣列,這裡簡單介紹一下:

空位的檢測 in

空位是沒有任何值,可以用 in 運算子檢測。我們可以根據 in 字元來檢測陣列某一項是否是空位。

const a = [,,,] // [empty × 3]
0 in a // false
const b = [1,2,3]
0 in b //true
複製程式碼

造成稀疏陣列的操作

  • delete 操作符

使用 delete 操作符可以將陣列項從陣列中刪除,陣列的長度並不會發生變化,而是會留下一個空位。

const b = [1,2,3]
delete b[0]
console.log(b) // [empty, 2, 3]
複製程式碼
  • 建構函式
const a = Array(3)
console.log(a) // [empty × 3]
複製程式碼
  • 在陣列字面量中省略值
[,,,] // [empty × 3]
複製程式碼
  • 指定陣列索引大於陣列長度
const c = []
c[10] = 0;
console.log(c) // [empty × 10, 0]
複製程式碼
  • 指定陣列長度大於當前陣列長度
const a = []
a.length = 10 // [empty × 10]
複製程式碼

我們在平時要儘量避免建立和使用稀疏陣列,因為在 ES6 之前的方法,對稀疏陣列的處理存在很多不統一的地方。

操作的不統一

ES5 對空位的處理,已經很不一致了,大多數情況下會忽略空位。

  • forEach(), filter(), reduce(), every() 和 some() 都會跳過空位。
  • map() 會跳過空位,但會保留這個值。
  • join() 和 toString() 會將空位視為 undefined,而 undefined 和 null 會被處理成空字串。

ES6 則是明確將空位轉為 undefined。

  • Array.from 方法會將陣列的空位,轉為 undefined。
  • 擴充套件運算子(…)也會將空位轉為 undefined。
  • copyWithin() 會連空位一起拷貝。
  • fill() 會將空位視為正常的陣列位置。
  • for…of 迴圈也會遍歷空位。
  • entries()、keys()、values()、find()和 findIndex() 會將空位處理成 undefined。

參考:阮一峰《ECMAScript 6 入門》- 陣列的擴充套件 – 陣列的空位

注意: 操作的不統一可能會有產生很多意料之外的結果,所以“牆裂”建議不要建立和使用稀疏陣列。

固定長度的 undefined 陣列建立

有些時候,我們並不關心陣列的內容是什麼,我們只是需要一個真正的陣列,並且能夠使用陣列的方法。

可以參考以下方法來建立:

  1. Array.apply
// 這個方法也是將一個類陣列物件轉為陣列物件。
// 在建立 undefined 值的陣列時有些奇怪和繁瑣,但是結果遠比 Array(3) 更準確可靠。
Array.apply(null, {length: 4}) // [undefined, undefined, undefined, undefined]
複製程式碼
  1. Array.from()
// 將類陣列物件轉換為陣列物件
Array.from({length: 4}) // [undefined, undefined, undefined, undefined]
複製程式碼
  1. 擴充套件運算子
[...Array(4)] // [undefined, undefined, undefined, undefined]
複製程式碼

總而言之

  • 不要建立和使用稀疏陣列
  • 避免使用 Array 建構函式建立陣列
  • 推薦物件字面量、of()from()、擴充套件運算子...建立陣列

參考連結

阮一峰《ECMAScript 6 入門》- 陣列的擴充套件 – 陣列的空位

建立 0-100 的陣列

稀疏陣列和 filter 方法

相關文章