筆者最近在深刻學習ES6中, 在寫代碼的過程當中用到了set,Map這兩個ES6新增的數據結構, 深切感覺到了它們的強大, 解決問題的能力。因而筆者決定寫一篇文章總結一下。並分享給你們,但願可以對你們有幫助。這篇文章主要給你們介紹了關於ES6學習筆記之map、set與數組、對象對比的相關資料, 下面讓咱們一塊兒走進set, Map的世界吧😄😄。html
舒適提示: Map和Set是ES6標準新增的數據類型,請根據瀏覽器的支持狀況決定是否要使用。前端
JavaScript的默認對象表示方式{}能夠視爲其餘語言中的Map或Dictionary的數據結構,即一組鍵值對。 可是JavaScript的對象{}有個小問題,就是鍵必須是字符串。但實際上Number或者其餘數據類型做爲鍵也是很是合理的。 爲了解決這個問題,最新的ES6規範引入了新的數據類型Map。git
Object是字符串-值,Map是值-值es6
// 初始化
let key1 = 12;
let value1 = 'test';
let m1 = new Map(); // m1: Map {}
let m2 = new Map([[key1, value1]]); // m2: Map { 12 => 'test' }
複製代碼
let m2 = new Map([['ou', 'yang'],['xing', 'hua']]);
console.log(m2.size) //輸出2
複製代碼
var m = new Map(); // 空Map
m.set('ouyang', 21); // 添加新的key-value
console.log(m); //Map { 'ouyang' => 21 }
m.set('ouyang', 22)
console.log(m); //Map { 'ouyang' => 22 }
複製代碼
注意:因爲一個key只能對應一個value,因此,屢次對一個key放入value,後面的值會把前面的值沖掉。github
let m2 = new Map([[12, 'yang']])
console.log(m2.get(12)) // 返回yang
複製代碼
let m2 = new Map([[12, 'yang']])
console.log(m2.has(12)); // true
console.log(m2.has(13)); // false
複製代碼
let m2 = new Map([[12, 'yang']])
m2.delete(12)
console.log(m2) // Map {}
複製代碼
let m2 = new Map([[12, 'yang'],['xing', 'hua']])
m2.clear()
console.log(m2) // Map {}
複製代碼
在此以前有必要說一下迭代器的做用, 迭代器是一種特殊對象,這種對象具備如下特色:數組
1,全部對象都有一個next方法 2,每次調用next方法,都會返回一個對象,該對象包含兩個屬性,一個是value, 表示下一個將要返回的值。另外一個是done,他是一個布爾值,用來表示該迭代器是否還有數據能夠返回. 3,迭代器還會保存一個內部指針指向當前集合中的值瀏覽器
想深刻了解迭代器的點這裏bash
let m2 = new Map([[12, 'yang'],['xing', 'hua']])
var iterator1 = m2.keys();
console.log(iterator1); //[Map Iterator] { 12, 'xing' }
console.log(iterator1.next().value); // 12
console.log(iterator1.next().value); // xing
複製代碼
let m2 = new Map([[12, 'yang'],['xing', 'hua']])
console.log(m2.values()) // [Map Iterator] { 'yang', 'hua' }
複製代碼
let m2 = new Map([[12, 'yang'],['xing', 'hua']])
var iterator1 = m2.entries();
console.log(iterator1); //[Map Iterator] { [ 12, 'yang' ], [ 'xing', 'hua' ] }
複製代碼
myMap.forEach(callback[, thisArg])數據結構
1.必要參數, callback爲每一個元素所要執行的函數。 2.可選參數, callback執行時其 this 的值。函數
callback 函數有三個參數
1.value -元素的值 2.key -元素的鍵 3.Map -當前正在被遍歷的對象
下面請看看例子
let Data = new Map();
let objKey = { num:10 };
let obj = {
num:5
}
Data.set("a", 1);
Data.set("b", 2);
Data.set("c", 3);
Data.forEach(function (value,key) {
console.log(value*this.num); // 輸出5 10 15
}, obj)
複製代碼
從上面的代碼能夠看出回調函數中this指向obj對象。
Map 轉爲數組最方便的方法,就是使用擴展運算符(...)。
const myMap = new Map()
.set(true, 7)
.set({foo: 3}, ['abc']);
[...myMap] // 輸出 [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
複製代碼
將數組傳入 Map 構造函數,就能夠轉爲 Map。
new Map([
[true, 7],
[{foo: 3}, ['abc']]
])
// Map {
// true => 7,
// Object {foo: 3} => ['abc']
// }
複製代碼
若是全部 Map 的鍵都是字符串,它能夠無損地轉爲對象。
function strMapToObj(strMap) {
let obj = Object.create(null);
for (let [k,v] of strMap) {
obj[k] = v;
}
return obj;
}
const myMap = new Map()
.set('yes', true)
.set('no', false);
strMapToObj(myMap)
// { yes: true, no: false }
複製代碼
若是有非字符串的鍵名,那麼這個鍵名會被轉成字符串,再做爲對象的鍵名。
function objToStrMap(obj) {
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}
objToStrMap({yes: true, no: false})
// Map {"yes" => true, "no" => false}
複製代碼
結合數組的map方法、filter方法,能夠實現 Map 的遍歷和過濾(Map 自己沒有map和filter方法)。
const map0 = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c');
const map1 = new Map(
[...map0].filter(([k, v]) => k < 3)
);
// 產生 Map 結構 {1 => 'a', 2 => 'b'}
const map2 = new Map(
[...map0].map(([k, v]) => [k * 2, '_' + v])
);
// 產生 Map 結構 {2 => '_a', 4 => '_b', 6 => '_c'}
複製代碼
寫到這裏,Map的基本用法和應用以及講完了,我相信應該能夠知足你們平常使用的需求吧。下面來看看set數據結構吧~~
- ES6 提供了新的數據結構 Set。它相似於數組,可是成員的值都是惟一的,沒有重複的值。Set 自己是一個構造函數,用來生成Set數據結構。
- Set和Map相似,也是一組key的集合,但不存儲value。因爲key不能重複,因此,在Set中,沒有重複的key。
都是一個存儲多值的容器,二者能夠互相轉換,可是在使用場景上有區別。以下:
const s = new Set();
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x)) //添加元素;
for (let i of s) {
console.log(i);
}
// 2 3 5 4
複製代碼
Set 函數能夠接受一個數組(或者具備 iterable 接口的其餘數據結構)做爲參數,用來初始化。 特色:
// 以數組爲參數
const set = new Set([1, 2, 3, 4, 4, '4'])
[...set] // [1, 2, 3, 4, '4']
set.size // 5
// 一個相似數組的帶 iterable 接口的對象
const set = new Set(document.querySelectorAll('div'))
複製代碼
Set 實例的屬性和方法和Map 實例的屬性和方法相似,下面簡要介紹一下。
const s = new Set();
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x)) //添加元素;
console.log(s.size) // 由於不能有重複元素因此輸出4
複製代碼
因爲Set只有key,並不存儲value(或者說鍵名和鍵值是同一個值),因此相對Map少了get()方法
const s = new Set()
s.add(1).add(2).add(2)
console.log(s) // Set { 1, 2 }
s.size // 2
s.has(1) // true
s.has(2) // true
s.has(3) // false
s.delete(2)
console.log(s) //Set { 1 }
s.size // 1
s.has(2) // false
複製代碼
方法名和Map的遍歷方法名同樣,下面來看用法
keys方法、values方法、entries方法返回的都是遍歷器對象。因爲 Set 結構沒有鍵名,只有鍵值(或者說鍵名和鍵值是同一個值),因此keys方法和values方法的行爲徹底一致。
const set = new Set(['a', 'b', 'c']);
for (let item of set.keys()) {
console.log(item); // a b c
}
for (let item of set.values()) {
console.log(item); // a b c
}
for (let item of set.entries()) {
console.log(item);
}
// 由於鍵名和鍵值是同一個值,因此輸出下面內容
// ["a", "a"]
// ["b", "b"]
// ["c", "c"]
set.forEach((value, key) => console.log(key + ' : ' + value))
// a: a
// b: b
// c: c
複製代碼
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 並集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
// 差集
let difference = new Set([...union].filter(x => !intersect.has(x)));
// Set {1}
複製代碼
若是想在遍歷操做中,同步改變原來的 Set 結構,目前沒有直接的方法,但有兩種變通方法。
// 方法一
let set = new Set([1, 2, 3]);
set = new Set([...set].map(val => val * 2));
// set的值是2, 4, 6
// 方法二
let set = new Set([1, 2, 3]);
set = new Set(Array.from(set, val => val * 2));
// set的值是2, 4, 6
複製代碼
因爲Set中元素的獨一無二,根據內存地址來進行判斷,因此若是有多個元素是引用型的話,儘管值相同,可是內存地址不一樣,那麼在Set對象中也將會存儲多份,和Map相似
let set = new Set([1, 2, 3, 3, 4]);
let arr = Array.from(set) //輸出[1,2,3,4]
複製代碼
var arr = [55, 44, 65];
var set = new Set(arr);
console.log(set) // Set { 55, 44, 65 }
console.log(set.size === arr.length);
console.log(set.has(65));
複製代碼
經過筆者的解析,發現Set、Map這兩種ES6新增的數據結構在必定程度解決了Object和Array的一些痛點。他讓咱們在選擇數據結構去解決具體問題時又多了兩種選擇,在開發過程當中,涉及到數據結構,能使用Map不使用數組,尤爲是複雜的數據結構。若是數據的要求比較高,強調惟一性,就使用Set,放棄使用Object作存儲。在數據結構中優先考慮Map、Set,放棄數組和Object。不過何時使用仍是要看應用場景的啦😄。但願這篇文章可以對你們有所幫助😄。
最後允許小生附上個人github地址 裏面記錄了我學習前端的點點滴滴,以爲有幫助的小哥哥小姐姐能夠給個小星星喲😄