一文帶你徹底搞懂JS中的Map與Set
定義
Set是一種叫做集合的數(shù)據(jù)結(jié)構(gòu)(結(jié)構(gòu)和Array很像),Set中的元素是唯一的,即沒有重復(fù)的(這點(diǎn)很重要)
Map是一種叫做字典的數(shù)據(jù)結(jié)構(gòu),和Object一樣保存鍵值對,但Map中鍵的范圍不限于字符串類型,各種類型的值(包括對象)都可以當(dāng)做是一個(gè)鍵或一個(gè)值
Set
Set
本身是一個(gè)構(gòu)造函數(shù),用來生成 Set
數(shù)據(jù)結(jié)構(gòu)
let set = new Set(); console.log(set); // {}
Set
對象可以存儲(chǔ)任意類型的值,但是用Set
構(gòu)造函數(shù)傳入的參數(shù)只能是可迭代對象,如:數(shù)組、字符串
// 當(dāng)你傳入一個(gè)整數(shù)時(shí),js會(huì)告訴你傳入的參數(shù)1不是可迭代對象 let set = new Set(1); console.log(set); // number 1 is not iterable // 傳入對象會(huì)報(bào)錯(cuò) let set = new Set({}); console.log(set); // object is not iterable // 必須是數(shù)組或字符串, let set1 = new Set('1'); console.log(set1); let set2 = new Set([1, 'true']); console.log(set2);
常見的方法
方法 | 說明 | 示例 |
---|---|---|
has() | 判斷是否有該值,返回布爾值 | set.has('name') |
add() | 向Set()添加元素,若有相同會(huì)覆蓋 | set.add('name', 'zxc') |
delete | 用于刪除某個(gè)元素,成功則返回true,失敗返回false | set.deldect('name') |
clear() | 用于清空 Set() 中所有的成員,沒有返回值 | set.clear() |
size 屬性 | 判斷 Set() 有多少個(gè)元素 | set.size |
let set = new Set() let arr = [1, 2] set.add(1).add(arr) set.add(function() { console.log(123); }) set.add({}) console.log(set); // { 1, [ 1, 2 ], [Function (anonymous)], {} } // has() 判斷元素 console.log(set.has(arr)); // true // size 判斷長度 console.log(set.size); // 4 // delete 刪除 console.log(set.delete(1)); // true console.log(set.delete(arr)); // true,set中存儲(chǔ)的對象,只能刪除這種有明確地址索引的,不然只能用clear() // clear 清除 set.clear() console.log(set); // {}
順序與迭代
Set()
結(jié)構(gòu)有四個(gè)遍歷的方法
方法 | 說明 | 示例 |
---|---|---|
keys() | 返回鍵的遍歷器 | set.keys() |
values() | 返回值的遍歷器 | set.values() |
entries() | 返回所有成員的遍歷器,包含鍵,值 | set.entries() |
forEach | 遍歷Set的所有成員 | set.forEach(function(), [this]) |
由于Set結(jié)構(gòu)沒有鍵名,所以其鍵名和鍵值是一致的
let set = new Set(['張三', '李四', '王五', 'true']); // 遍歷鍵 console.log(set.keys()); // { '張三', '李四', '王五', 'true' } // 遍歷值 console.log(set.values()); // { '張三', '李四', '王五', 'true' } // 返回鍵值 console.log(set.entries()); /* { [ '張三', '張三' ], [ '李四', '李四' ], [ '王五', '王五' ], [ 'true', 'true' ] }*/ ? // forEach() 循環(huán) let set = new Set(['張三', '李四', '王五', 'true']) set.forEach(function(value, key) { console.log(key + ':' + value); }) /* 張三:張三 李四:李四 王五:王五 true:tru*/
也可以使用 for...of
或 for...in
// 遍歷值 for (let value of set) { console.log(value);} // 遍歷鍵 for (let key in set) {console.log(key);}
類型轉(zhuǎn)換
Set
類型可以與其它類型的值進(jìn)行轉(zhuǎn)換
Array
轉(zhuǎn)換為 Set
let arr = [1, 2, 3, 4] let set = new Set(arr) console.log(set); // { 1, 2, 3, 4 }
Set
轉(zhuǎn)換為 Array
:可以通過擴(kuò)展運(yùn)算符 ...
來實(shí)現(xiàn)
let set = new Set([1, 2, 3, 4]) console.log([...set]); // [ 1, 2, 3, 4 ]
String
轉(zhuǎn)換為 Set
let str = '張三' let set = new Set(str) console.log(set); // { '張', '三' }
Set 的作用
去重
利用Set
不重復(fù)性可以用于數(shù)組的去重
// 將數(shù)組轉(zhuǎn)換為Set,再將Set轉(zhuǎn)換為數(shù)組 let arr = [1, 1, 4, 1, 2, 3, 1, 2] let set = new Set(arr) console.log([...set]); // [ 1, 4, 2, 3 ]
并集
let arr1 = [1, 1, 4, '1', 2, 3] let arr2 = [5, 1, '2'] let set = new Set([...arr1, ...arr2]) console.log([...set]); // [ 1, 4, '1', 2, 3, 5, '2' ]
PS:Set
不允許強(qiáng)制轉(zhuǎn)換,1 和 ‘1’ 被認(rèn)為是不同的值
Set總結(jié)
Set
最大的特點(diǎn)就是它的元素是唯一的,基于這個(gè)特性可以用于去重Set
可以存儲(chǔ)任意類型的值,但是初始化的時(shí)候只能傳入可迭代對象Set
可以與Array
進(jìn)行互相轉(zhuǎn)換,也可以把String
轉(zhuǎn)換為Set
類型- 擴(kuò)展運(yùn)算符和
Set
結(jié)構(gòu)相結(jié)合實(shí)現(xiàn)數(shù)組或字符串去重
Map
在ES6以前,在js中實(shí)現(xiàn) 鍵/值式 存儲(chǔ)可以使用 Object
來高效完成,ES6新增了一種新的集合類型 Map
它最大的特點(diǎn)就是:Map
中鍵的范圍不限于字符串類型,各種類型的值(包括對象)都可以當(dāng)做是一個(gè)鍵或一個(gè)值
所以Object
和 Map
鍵值類型:
Object
:字符串/Symbol類型: 任意類型
Map
:任意類型: 任意類型
初始化Map
創(chuàng)建一個(gè)空map
// 必須是以這種方式創(chuàng)建 let map= new Map();
給Map
構(gòu)造函數(shù)傳入一個(gè)可迭代對象,需要包含鍵值對,每個(gè)鍵值對會(huì)按照迭代順序映射到實(shí)例當(dāng)中
const map = new Map([ ['name', 'cyf'], ['age', 18] ]); console.log(map); // {"name" => "zxc", "age" => 18}
Map常用方法
方法 | 說明 | 示例 |
---|---|---|
get() | 通過鍵來獲取值,如果沒有該鍵,則返回 undefined | map.get('name') |
has() | 判斷是否有該鍵,返回布爾值 | map.get('name') |
set() | 用于設(shè)置對應(yīng)的鍵值對,若有相同會(huì)覆蓋 | map.set('name', 'zxc') |
delete() | 用于刪除某個(gè)鍵,成功則返回true,失敗返回false | map.deldect('name') |
clear() | 用于清空 Map() 中所有的成員,沒有返回值 | map.clear() |
let map = new Map([ ['namer', '張三'], ['age', 2] ]); ? // 獲取namer console.log(map.get('namer')); // 張三 ? // 判斷namer console.log(map.has('age')); // 2 ? // 設(shè)置鍵值對 console.log(map.set('sex', '其它')); // { 'namer' => '張三', 'age' => 2, 'sex' => '其它' } // 可連續(xù)設(shè)置 console.log(map.set('id', 0).set('hobby', '講段子')); ? // size屬性,獲取map長度 console.log(map.size); // 5 ? // 刪除某個(gè)鍵 console.log(map.delete('id')); // true ? // 清空map map.clear() console.log(map); // {}
一個(gè)key只能對應(yīng)一個(gè)value,多次對一個(gè)key放入value,之前的值會(huì)被覆蓋
let map =new Map() map.set('Amy',"女") map.set('Amy',"男") console.log(map)
順序與迭代
與 Object
類型的一個(gè)差異是:Map
實(shí)例會(huì)維護(hù)鍵值對的插入順序,因此可以根據(jù)順序執(zhí)行迭代操作
Map
提供了3個(gè)遍歷器和一個(gè)遍歷方法
方法 | 說明 | 示例 |
---|---|---|
keys() | 返回鍵的遍歷器 | map.keys() |
values() | 返回值的遍歷器 | map.values() |
entries() | 返回所有成員的遍歷器,包含鍵,值 | map.entries() |
forEach | 遍歷Map的所有成員 | map.forEach(function(), [this]) |
let map = new Map().set('namer', '張三').set('age', 2).set('sex', '其它') ? // 獲取鍵 let keys = map.keys() console.log(keys); ? // 獲取值 let values = map.values() console.log(values); ? // 獲取鍵值對 console.log(map.entries()); // { [ 'namer', '張三' ], [ 'age', 2 ], [ 'sex', '其它' ] } ? for (let [key, value] of map) { console.log(key + ':' + value); } // namer:張三 // age:2 // sex:其它 ? // forEach 循環(huán) map.forEach(function(value, index) { console.log(index + ':' + value); }) ? // namer:張三 // age:2 // sex:其它
Map與Object的區(qū)別
鍵名類型
Object
只能接收兩種類型的鍵名:String
和Symbol
Map
能夠接受任意類型的鍵名
Map
鍵名:
let map = new Map(); map.set(1, 'Number').set(true, 'Boolean').set({ '鍵名': '鍵值' }, 'Object').set(function() {}, 'Function') console.log(map); // { 1 => 'Number', true => 'Boolean', { '鍵名': '鍵值' } => 'Object', [Function (anonymous)] => 'Function'}
Object
鍵名
let obj = {} obj[1] = 'Number'; obj[true] = 'Boolean'; obj[{ '鍵名': '鍵值' }] = 'Object'; obj[function() {}] = 'Function' ? console.log(obj); // { '1': 'Number', true: 'Boolean', '[object Object]': 'Object', 'function() {}': 'Function' }
雖然說Object
可以接受其他類型的鍵名,當(dāng)時(shí)js都會(huì)隱式地將其轉(zhuǎn)換為字符串
迭代
Map
是可以迭代的,用forEach
循環(huán)或for...of
Object
是不能直接進(jìn)行迭代的
Object
遍歷需要借助對象的靜態(tài)方法
let obj = { 'namer': '張三', 'age': 2, 'sex': '其它' } ? // 遍歷鍵 for (let key of Object.keys(obj)) { console.log(key); }
還可以是:
for (let value of Object.values(obj)) {} ? for (let keyValue of Object.entries(obj)) {} ? for (let [key, value] of Object.entries(obj)) {}
當(dāng)然可以使用 for...in
遍歷鍵
for (let key in obj) { console.log(key); // namer age sex }
順序和長度
長度
Map
保存對長度的跟蹤,可直接使用size
,其時(shí)間事件復(fù)雜度為O(1)
- 對于
Object
而言,想要獲取對象長度需要對于其進(jìn)行迭代,其時(shí)間復(fù)雜度為O(n)
順序
Map
始終是保持鍵值對插入時(shí)的順序Object
則不是,不過ES6之后就會(huì)可以按順序保存了,只是通過隱式轉(zhuǎn)換為字符串的鍵就亂序了
總結(jié)
Map
的鍵可以是任意類型,并且可以用forEach
等迭代Map
的鍵值對是根據(jù)set
設(shè)置的順序存儲(chǔ)的Map
獲取長度就是用size
屬性直接返回,時(shí)間復(fù)雜度為O(1)
Map
缺點(diǎn)就是不能使用[]
和點(diǎn)
來設(shè)置和獲取鍵值,只能用set
和get
來替換- 固定大小內(nèi)存,
Map
大約可以比Object
多存儲(chǔ)50%的鍵值對
WeakSet 和 WeakMap
WeakSet
WeakSet
是一種 “弱集合”類型,其集合中的值只能是對象
由于Set結(jié)構(gòu)沒有鍵名,所以其鍵名和鍵值是一致的
let set = new Set(['張三', '李四', '王五', 'true'])
方法 | 說明 |
---|---|
has() | 判斷是否有該值,返回布爾值 |
add() | 向Set()添加元素,若有相同會(huì)覆蓋 |
delete() | 用于刪除某個(gè)元素,成功則返回 true,失敗返回 false |
1、創(chuàng)建一個(gè)空的WeakSet
let WeakSet = new WeakSet();
2、初始化WeakSet
構(gòu)造函數(shù)可以傳入一個(gè)迭代對象,可迭代對象中的值必須得是對象
let x = { id: 1 }, y = { id: 2 } let weakSet = new WeakSet([x, y]); console.log(weakSet); ? console.log(weakSet.has(x)); // true console.log(weakSet.delete(x)); // true
WeakSet
中沒有clear
方法 和 size
屬性
因?yàn)?nbsp;WeakSet
中的值任何時(shí)候都可能被銷毀,所以沒必要提供迭代的功能,也用不著先clear
這個(gè)清空的功能
另外,因?yàn)?nbsp;WeakSet
的成員可以被垃圾回收機(jī)制回收,所以可以用來保存DOM
節(jié)點(diǎn),不容易造成內(nèi)存泄露
WeakMap
weakMap
是 Map
的變體,它們的方法基本是一樣的,區(qū)別在于內(nèi)部分配的工作方式
weakMap
只接受引用類型的數(shù)據(jù)作為鍵名,如:數(shù)組、函數(shù)、對象等
1、創(chuàng)建一個(gè)空的WeakMap
let WeakMap = new WeakMap();
2、初始化WeakMap
let weakMap = new WeakMap(); let x = { id: 1 }, y = { id: 2 } weakMap.set(x, '張三') weakMap.set(y, 2) console.log(weakMap.get(x)); // 張三 console.log(weakMap.get(y)); // 2 console.log(weakMap.has(x)); // true console.log(weakMap.delete(x)); // true
WeakMap
中沒有clear
方法 和 size
屬性
到此這篇關(guān)于一文帶你徹底搞懂JS中的Map與Set的文章就介紹到這了,更多相關(guān)JS Map Set內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS組件Bootstrap實(shí)現(xiàn)圖片輪播效果
這篇文章主要為大家詳細(xì)介紹了JS組件Bootstrap實(shí)現(xiàn)圖片輪播效果的具體代碼,對圖片輪播效果感興趣的小伙伴們可以參考一下2016-05-05微信小程序?qū)崿F(xiàn)富文本圖片寬度自適應(yīng)的方法
小程序里圖片會(huì)顯示不全,這時(shí)就應(yīng)該做相應(yīng)的處理,使小程序里圖片顯示正確,這篇文章主要介紹了微信小程序?qū)崿F(xiàn)富文本圖片寬度自適應(yīng)的方法,感興趣的小伙伴們可以參考一下2019-01-01JavaScript實(shí)現(xiàn)替換字符串中最后一個(gè)字符的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)替換字符串中最后一個(gè)字符的方法,涉及javascript字符串的轉(zhuǎn)換與運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2017-03-03uni-app中使用手機(jī)號一鍵登錄的詳細(xì)圖文教程
最近剛接觸了uni-app,用于開發(fā)微信小程序,設(shè)計(jì)到了微信授權(quán)登錄,下面這篇文章主要給大家介紹了關(guān)于uni-app中使用手機(jī)號一鍵登錄的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01