es6(三set和map資料結構)
阿新 • • 發佈:2018-11-20
es6中提供了一個新的資料結構Set,他有點類似陣列,但和陣列不同的是,在裡面你如果寫入重複的值的話,他不會顯示重複值。
const s =new Set(); [2,3,4,5,6,6,6,7,8,9].forEach(x => s.add(x)); for (let i of s){ console.log(i) } //2,3,4,5,6,7,8,9
平常使用當然不需要像上面那樣麻煩了,只需要最簡單的方式來進行獲取輸出就行了
// 用中括號括起來,可以得到不重複的陣列,用大括號括起來,可以得到物件和總共多少個 const set = new Set([1, 2, 3, 4, 4]); [...set] // [1, 2, 3, 4] {...set} //{4,array(3)} // .size的輸出是直接獲取有多少個不重複的物件 const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]); items.size // 5
往set中去新增物件,就像在函式中進行.push一樣
//用.add方法往set中新增物件,這裡說明一下NAN值,在這最後輸出的是一個NAN說明兩個NAN是相等的 let set = new Set(); let a = NaN; let b = NaN; set.add(a); set.add(b); set // Set {NaN} //但是隻要新增物件的話就不同了,兩個物件是永遠不相等的 set.add({}); set.size // 1 set.add({}); set.size // 2 //上面可以看出,添加了兩次物件最後輸出的 值是2,說明兩個相同的物件新增進去,不會出現去重現象
介紹下四個操作方法
- add(value):新增某個值,返回 Set 結構本身。 - delete(value):刪除某個值,返回一個布林值,表示刪除是否成功。 - has(value):返回一個布林值,表示該值是否為Set的成員。 - clear():清除所有成員,沒有返回值。
Array.from方法可以將Set結構轉為陣列(在我看來這個方法沒啥用出都,直接用上面的方法就已經成為了陣列,何必再去轉一回呢)
const items = new Set([1, 2, 3, 4, 5]); const array = Array.from(items); 瞭解下就好 function dedupe(array) { return Array.from(new Set(array)); } dedupe([1, 1, 2, 3]) // [1, 2, 3]
介紹四個遍歷的方法
- keys():返回鍵名的遍歷器 - values():返回鍵值的遍歷器 - entries():返回鍵值對的遍歷器 - forEach():使用回撥函式遍歷每個成員
平常就直接用set結構就可以了,set的遍歷順序就是插入順序,由於set結構沒有鍵名只有鍵值,所以keys方法和values方法的行為是完全一樣的
let set = new Set(['red', 'green', 'blue']); for (let item of set.keys()) { console.log(item); } // red // green // blue for (let item of set.values()) { console.log(item); } // red // green // blue //entries方法,把鍵值和鍵名全都返回回來了 for (let item of set.entries()) { console.log(item); } // ["red", "red"] // ["green", "green"] // ["blue", "blue"]
set實現的並集,交集,差集
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([...a].filter(x => !b.has(x))); // Set {1}
weakSet結構和Set類似,但是weakSet結構只能放入物件,不能放入其他型別的值,建立一個新的weakSet資料結構,使用的時候會把成員轉換成物件輸出
const a = [[1, 2], [3, 4]]; const ws = new WeakSet(a); // WeakSet {[1, 2], [3, 4]}
這裡有個面向物件的問題說一下,可能理解的不全面,湊活著理解吧
const b =[['3'] , ['4']] const ws = new WeakSet(b); console.log(ws) //WeakSet {_c: WeakSet} // _c: WeakSet {Array(1), Array(1)} // __proto__: WeakSet 如果 const b = [3,4] const ws = new WeakSet(b); //這樣就會報錯的,因為b裡面的值不是陣列,是個number
WeakSet 沒有size
屬性,沒有辦法遍歷它的成員。
Map建構函式
const map = new Map([ ['name', '張三'], ['title', 'Author'] ]); map.size // 2 map.has('name') // true map.get('name') // "張三" map.has('title') // true map.get('title') // "Author"
注意:只有同一個物件的引用,Map結構才視為同一個鍵
const map = new Map(); map.set(['a'], 555); map.get(['a']) // undefined
//表面是針對同一個鍵,但實際上這是兩個值,記憶體地址是不一樣的,因此get方法無法讀取該鍵,返回undefined const map = new Map(); const k1 = ['a']; const k2 = ['a']; map .set(k1, 111) .set(k2, 222); map.get(k1) // 111 map.get(k2) // 222
Map結構原生的遍歷方法
- keys():返回鍵名的遍歷器。 - values():返回鍵值的遍歷器。 - entries():返回所有成員的遍歷器。 - forEach():遍歷 Map 的所有成員。
使用方法
需要特別注意的是,Map 的遍歷順序就是插入順序。 const map = new Map([ ['F', 'no'], ['T', 'yes'], ]); for (let key of map.keys()) { console.log(key); } // "F" // "T" for (let value of map.values()) { console.log(value); } // "no" // "yes" for (let item of map.entries()) { console.log(item[0], item[1]); } // "F" "no" // "T" "yes" // 或者 for (let [key, value] of map.entries()) { console.log(key, value); } // "F" "no" // "T" "yes" // 等同於使用map.entries() for (let [key, value] of map) { console.log(key, value); } // "F" "no" // "T" "yes" 上面程式碼最後的那個例子,表示 Map 結構的預設遍歷器介面(Symbol.iterator屬性),就是entries方法。 map[Symbol.iterator] === map.entries // true
Map轉為陣列結構,和set差不太多
const map = new Map([ [1, 'one'], [2, 'two'], [3, 'three'], ]); [...map.keys()] // [1, 2, 3] [...map.values()] // ['one', 'two', 'three'] [...map.entries()] // [[1,'one'], [2, 'two'], [3, 'three']] [...map] // [[1,'one'], [2, 'two'], [3, 'three']]
與其他資料結構互相轉換
(1)Map 轉為陣列 前面已經提過,Map 轉為陣列最方便的方法,就是使用擴充套件運算子(...)。 const myMap = new Map() .set(true, 7) .set({foo: 3}, ['abc']); [...myMap] // [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ] (2)陣列 轉為 Map 將陣列傳入 Map 建構函式,就可以轉為 Map。 new Map([ [true, 7], [{foo: 3}, ['abc']] ]) // Map { // true => 7, // Object {foo: 3} => ['abc'] // } (3)Map 轉為物件 如果所有 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 } 如果有非字串的鍵名,那麼這個鍵名會被轉成字串,再作為物件的鍵名。 (4)物件轉為 Map 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} (5)Map 轉為 JSON Map 轉為 JSON 要區分兩種情況。一種情況是,Map 的鍵名都是字串,這時可以選擇轉為物件 JSON。 function strMapToJson(strMap) { return JSON.stringify(strMapToObj(strMap)); } let myMap = new Map().set('yes', true).set('no', false); strMapToJson(myMap) // '{"yes":true,"no":false}' 另一種情況是,Map 的鍵名有非字串,這時可以選擇轉為陣列 JSON。 function mapToArrayJson(map) { return JSON.stringify([...map]); } let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']); mapToArrayJson(myMap) // '[[true,7],[{"foo":3},["abc"]]]' (6)JSON 轉為 Map JSON 轉為 Map,正常情況下,所有鍵名都是字串。 function jsonToStrMap(jsonStr) { return objToStrMap(JSON.parse(jsonStr)); } jsonToStrMap('{"yes": true, "no": false}') // Map {'yes' => true, 'no' => false} 但是,有一種特殊情況,整個 JSON 就是一個數組,且每個陣列成員本身,又是一個有兩個成員的陣列。這時,它可以一一對應地轉為 Map。這往往是 Map 轉為陣列 JSON 的逆操作。 function jsonToMap(jsonStr) { return new Map(JSON.parse(jsonStr)); } jsonToMap('[[true,7],[{"foo":3},["abc"]]]') // Map {true => 7, Object {foo: 3} => ['abc']}