每日 30 秒 ⏱ 陣列也會禿頂

zhangxiangliang發表於2019-03-24

簡介

稀疏陣列、陣列效能、密集陣列、遍歷

除了程式設計師會禿頂,陣列也會禿頂。什麼你不相信我?那我證明給你看:

let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

delete arr[2]

// 輸出 [0, 1, empty, 3, 4, 5, 6, 7, 8, 9]
console.log(arr)

// 輸出 0 1 3 4 5 6 7 8 9
arr.forEach(i => console.log(i))
複製程式碼

拔掉(delete) arr 的第 3 根 頭髮(arr[2]) 時,直接硬生生的出現了一個 空毛囊(empty),這難道不是陣列禿頂了嘛?數(forEach) 一下頭髮,確實沒有把空毛囊算進去,這下你相信了把陣列也會禿頂,那不如讓我們好好研究研究?

班級點名

上學時最常見的一個場景便是老師點名,按著學號連續的讀出學生的名字並在記錄本上打上勾,速度是相當的快。反過來隨機叫一個學生的名字並在記錄本上,需要在記錄本上找到這個名字並打上勾,速度是相當慢的。

在上面兩個場景中一個使用了 索引 而另外一個使用了 hash,而在 Array 中也存在類似的現象。

在 Array 若是執行了連續陣列操作如 Array.prototype.pop()Array.prototype.unshift() 來運算元組,由於整個空間都是 連續的 使用索引直接定位,遍歷起來非常快,這種 Array 叫做 密集陣列

而 Array 若是執行了非連續陣列操作如 delete arr[2]、賦值超出當前陣列長度、賦值為非連續索引 來運算元組,由於空間的 連續性 被破壞了,只能通過 hash 定位,遍歷起來就會變慢。這種 Array 叫做 稀疏陣列,你可以理解為它被物件化了使得更像是一個 Object。

稀疏陣列通常在實現上比密集陣列更慢更耗記憶體,在這樣的陣列中查詢元素變得跟常規物件的查詢一樣失去了效能的優勢。所以我們在使用 Array 要儘量避免破壞它的連續性,儘量使用陣列相關的方法來操作它。

在控制檯檢視

其實在控制檯中可以非常明顯的看出密集陣列稀疏陣列的索引是否連續:

對比

稀疏陣列轉換密集陣列

利用 Array.prototype.apply
// 進行一下破壞連續性的操作
let arr = [1, ,3, 4];
delete arr[3];
arr['a'] = 5;

// 輸出 [1, empty, 3, empty, a: 5]
console.log(arr);

// 進行轉換
arr = Array.apply(null, arr);

// 輸出 [1, undefined, 3, undefined]
console.log(arr);
複製程式碼
利用 Array.prototype.from
// 進行一下破壞連續性的操作
let arr = [1, ,3, 4];
delete arr[3];
arr['a'] = 5;

// 輸出 [1, empty, 3, empty, a: 5]
console.log(arr);

// 進行轉換
arr = Array.from(arr);

// 輸出 [1, undefined, 3, undefined]
console.log(arr);
複製程式碼
利用 spread 運算子
// 進行一下破壞連續性的操作
let arr = [1, ,3, 4];
delete arr[3];
arr['a'] = 5;

// 輸出 [1, empty, 3, empty, a: 5]
console.log(arr);

// 進行轉換
arr = [...arr];

// 輸出 [1, undefined, 3, undefined]
console.log(arr);
複製程式碼
注意 new Array

要注意 new Array 只是會生成一個指標指向連續的空間,此時它也是非連續的:

let arr = new Array(4);

// 輸出 [empty × 4]
console.log(arr);
複製程式碼

傳入空引數

利用 null, undefined 呼叫函式

在呼叫函式的時候有時候,我們需要跳過一些引數可以使用 nullundefined 來實現:

method('a', null, 'c');
method('a', undefined, 'c');
複製程式碼

當然也可以利用稀疏陣列:

method(...['a',, 'c']);
複製程式碼

一起成長

在困惑的城市裡總少不了並肩同行的 夥伴 讓我們一起成長。

  • 如果您想讓更多人看到文章可以點個 點贊
  • 如果您想激勵小二可以到 Github 給個 小星星
  • 如果您想與小二更多交流新增微信 m353839115

微信公眾號

本文原稿來自 PushMeTop

相關文章