一文搞懂Map與Set的用法和區(qū)別解析
前言
作為前端開發(fā)人員,我們最常用的一些數(shù)據(jù)結構就是 Object、Array 之類的,畢竟它們使用起來非常的方便。往往有些剛入門的同學都會忽視 Set 和 Map 這兩種數(shù)據(jù)結構的存在,因為能用 set 和 map 實現(xiàn)的,基本上也可以使用對象或數(shù)組實現(xiàn),而且還更簡單。
但是,存在必然合理,當你真正了解 Map 和 Set 之后,你就會發(fā)現(xiàn)它們原來時如此美好!
1.基本概念
我們先來了解以下 Map 和 Set 的基本概念,這樣才能幫助我們更好的使用。雖然我們通常把這兩種數(shù)據(jù)結構混合著來講,但事實上它們它們還是有挺大區(qū)別的!
1.1 Map(字典)
想要迅速了解一個新的數(shù)據(jù)結構或 API 是,查看官網(wǎng)是一個不錯的選擇。Map 在官網(wǎng)上也有解釋,我們一起來看下。
官網(wǎng)解釋:
Map對象保存鍵值對,并且能夠記住鍵的原始插入順序。任何值(對象或者原始值)都可以作為一個鍵或一個值。
官網(wǎng)的這句話非常精煉,我們從上面這句話中總結如下幾個關鍵詞:
- 鍵值對
- 記住插入順序
- 任意值作為鍵
一看到鍵值對,難免會想到對象。事實確實如此,Map 與我們平常所用的對象非常類似,它是一種類對象的數(shù)據(jù)結構,所以我們通常稱它為 Map 對象。
但是我們可以把它說得更為官方一點:Map 字典。關于程序中字典的概念大家可以下去了解一下。
特點總結:
Map對象這種數(shù)據(jù)結構和和對象類型,都已鍵值對的形式存儲數(shù)據(jù),即key-vlue形式。Map對象存儲的數(shù)據(jù)是有序的,而我們平常使用的對象是無序的,所以通常當我們需要使用對象形式(鍵值對)存儲數(shù)據(jù)且需要有序時,采用Map對象進行存儲。Map對象的鍵值可以是任意類型,我們平時使用的對象只能使用字符串作為鍵。
1.2 Set(集合)
和 Map 類似,我們同樣先來看一看官網(wǎng)是怎么解釋 Set 這個數(shù)據(jù)結構的。
官網(wǎng)的解釋:
Set 對象允許你存儲任何類型的唯一值,無論是原始值或者是對象引用。
Set 的解釋比 Map 的解釋還要精煉,我們從中提取出幾個關鍵詞:
- 任何類型
- 唯一值
上面關鍵詞中我們需要重點關注“唯一值”,這說明使用 Set 存儲的數(shù)據(jù)是不會重復的,除此之外,Set 也是一個對象,但是它是一個類數(shù)組對象,也就是說它長得像數(shù)組,我們通常直接稱它為 Set 對象。
當然也可以官方一點的稱它:Set 集合。
特點總結:
Set對象是一個類數(shù)組對象,它長得就很像數(shù)組。Set對象存儲的值是不重復的,所以我們通常使用它來實現(xiàn)數(shù)組去重。Set對象存儲的數(shù)據(jù)不是鍵值對的形式,而且它可以存儲任何類型的數(shù)據(jù)。
2.基本使用
我們平常使用 Array 或者 Object 的時候,都是直接采用[變量] = []、[變量] = {}的形式來進行初始化。而這里我們所講的 Map 和 Set 數(shù)據(jù)結構它們都是以構造函數(shù)的形式出現(xiàn)的,所以我們通常使用 new Set()或者 new Map()的形式初始化的。
2.1 Map 基本使用
初始化 map 對象:
let myMap = new Map();
初始化 map 時傳入數(shù)據(jù):
由于 Map 對象是一個構造函數(shù),所以我們在初始化的時候可以傳入默認數(shù)據(jù)的,只不過我們需要注意傳入默認數(shù)據(jù)的格式,它默認接收一個二維數(shù)組。
let defaultMap = new Map([['name', '張三'], ['age', 20]]);
打印出來看看結果:

插入數(shù)據(jù):
myMap.set('name', '小豬課堂'); // 字符串作為鍵
myMap.set(12, '會飛的豬'); // number 類型作為鍵
myMap.set({}, '知乎'); // 對象類型作為鍵我們先打印出來看看結果:

獲取長度:
我們傳統(tǒng)的對象可以通過 Object.key().length 來獲取對象長度,而 map 對象自帶 size 屬性獲取對象長度。
let myMapSize = myMap.size;
獲取值:
let objKey = {};
myMap.set('name', '小豬課堂'); // 字符串作為鍵
myMap.set(12, '會飛的豬'); // number 類型作為鍵
myMap.set(objKey, '知乎'); // 對象類型作為鍵
let name = myMap.get('name');
let age = myMap.get(12);
let any = myMap.get(objKey);
console.log(name, age, any); // 小豬課堂 會飛的豬 知乎上段代碼中需要注意的是不能使用 myMap.get({})的形式獲取數(shù)據(jù),因為 objKey!=={}。
刪除某個值:
myMap.delete('name');
判斷某個值是否存在:
myMap.has('name'); // 返回 bool 值
2.2 Set 基本使用
Set對象的使用方式和Map對象的使用方式非常的類似,只不過存儲的數(shù)據(jù)格式不一樣罷了。這里需要注意的Set對象存儲的不是鍵值對形式,它只存儲了值,沒有鍵,就和數(shù)組類似。
初始化Set對象:
let mySet = new Set();
初始化Set對象帶有默認值:
和Map類似,Set初始化時也可以初始化默認數(shù)據(jù)。
let defaultSet = new Set(['張三', 12, true]);
一起來看看輸出結果:

插入數(shù)據(jù):
mySet.add(1);
mySet.add('小豬課堂');
打印結果:

獲取長度:
let mySetSize = mySet.size;
獲取值:
由于Set對象存儲的不是鍵值對形式,所以未提供get方法獲取值,我們通常遍歷它獲取值:
mySet.forEach((item) => {
console.log(item)
})
刪除某個值:
mySet.delete(1);
判斷某個值是否存在:
mySet.has(1); // 返回Boolean值
3.Map和Set區(qū)別
如果我們學會了它們兩者如何使用,或多或少都知道它們的區(qū)別在哪里,我們這里為大家總結一下它們的區(qū)別要點:
Map和Set查找速度都非???,時間復雜度為O(1),而數(shù)組查找的時間復雜度為O(n)。Map對象初始化的值為一個二維數(shù)組,Set對象初始化的值為一維數(shù)組。Map對象和Set對象都不允許鍵重復(可以將Set對象的鍵想象成值)。Map對象的鍵是不能改的,但是值能改,Set對象只能通過迭代器來更改值。
4.使用場景介紹
4.1 Set對象使用場景
數(shù)組去重
這是大家很熟悉的一種場景,使用Set對象的唯一性值特性方便的給我們數(shù)組去重。
代碼如下:
let arr = [1, 2, 3, 4, 5, 6, 3, 2, 5, 3, 2]; console.log([...new Set(arr)]); // [1, 2, 3, 4, 5, 6]
需要注意的是Set對象是一個類數(shù)組,我們使用...擴展運算符將一個類數(shù)組轉化為了一個真正的數(shù)組。
4.2 Map對象使用場景
數(shù)字類型充當鍵
代碼如下:
let errors = new Map([ [400, 'InvalidParameter'], [404, 'Not found'], [500, 'InternalError'] ]); console.log(errors);
輸出結果:

我們可以使用Map對象建立一個請求狀態(tài)碼對象字典,因為狀態(tài)碼是數(shù)字類型,所以使用Map對象很合適。
除了該場景外,如果需要保證對象的順序,那么也是可以使用Map對象的。
5.思考點
前面我們說Set和Map的插入刪除效率為什么很高呢?
這里簡單講一下,更加深入需要大家自己下去好好學習一下數(shù)據(jù)結構了。
簡述原因:
map和set存儲的所有元素都是以節(jié)點的方式來進行存儲的,這種節(jié)點結構和鏈表有點類似。我們都知道鏈表的特點是插入和刪除都非???,時間復雜度為O(1),兩個節(jié)點通過指針相連,刪除或者增加元素時,我們只是重新更改了指針的指向,不想數(shù)組那樣,摻入或刪除之后需要重新排序。
總結
Set對象和Map對象有很多優(yōu)點的,比如說性能比較好等等,我們需要一一去體會它們的優(yōu)缺點。你不如在每次創(chuàng)建數(shù)據(jù)結構之前想一想:使用Object更好還是Map更好呢?使用Array更好還是Set更好呢? 當然,如果深究Set和Map底層原理之后,你會發(fā)現(xiàn)它們的實現(xiàn)原理就是紅黑樹。
到此這篇關于一文搞懂Map與Set的用法和區(qū)別的文章就介紹到這了,更多相關Map與Set用法內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
DD_belatedPNG,IE6下PNG透明解決方案(國外)
今天介紹DD_belatedPNG,只需要一個理由,就是它支持backgrond-position與background-repeat.這是其他js插件不具備的.2010-12-12
Javascript:為input設置readOnly屬性(示例講解)
本篇文章主要是對Javascript中為input設置readOnly屬性的示例代碼進行了介紹。需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12
JavaScript進階教程之函數(shù)的定義、調用及this指向問題詳解
這篇文章主要給大家介紹了關于JavaScript進階教程之函數(shù)的定義、調用及this指向問題的相關資料,文中通過實例代碼介紹的非常詳細,對大家學習或者使用js具有一定的參考學習價值,需要的朋友可以參考下2022-09-09

