Set和Map數據結構。

ES6提供了新的數據結構Set,它相似與數組,可是成員值都是惟一的,沒有重複的值。 Set自己是一個構造函數,用來生成Set數據結構。

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
}

上面代碼經過add()方法向Set結構加入成員,結果代表Set結構不會添加劇復的值。
Set函數能夠接受一個數組做爲參數,用來初始化。數組

//例子1
const set = new Set([1,2,3,4,4]);
[...set];//[1,2,3,4]
//例子2
const items = new Set([1,2,3,4,5,5,5,5]);
items.size//5
//例子3
const set = new Set(document.querySelectorAll('div'));

上面代碼中,例一和例二都是Set函數接受數組做爲參數,例三是接受相似數組的對象做爲參數。
上面代碼也展現了一種去除數組重複成員的方法。數據結構

//去除數組的重複成員
[...new Set(array)]
//去除字符串裏面的重複字符
[...new Set('ababbc')].join('');//'abc'
//下面代碼向Set實例添加了兩個NaN,可是隻能加入一個。這代表在Set內部兩個NaN是相等。
let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
set // Set {NaN}
//另外,兩個對象老是不相等的。
let set = new Set();
set.add({});
set.size // 1
set.add({});
set.size // 2

Set實例的屬性和方法

Set結構的實例有如下屬性。函數

-Set.prototype.constructor:構造函數,默認就是set函數。
-Set.prototype.size:返回Set實例的成員總數。

Set實例的方法分爲兩大類:操做方法和遍歷方法。下面先介紹四個操做方法。this

-add(value):添加某個值,返回Set結構自己。
-delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功。
-has(value):返回一個布爾值,表示該值是否爲Set的成員。
-clear();清除全部成員,沒有返回值。

下面這些屬性和方法的示例以下:prototype

s.add(1).add(2).add(2);
//注意2被加入了兩次
s.size//2
s.has(1)//true
s.has(2)//true
s.has(3)//false
s.delete(2);
s.has(2)//false

下面是一個對比,看看在判斷是否包括一個鍵上面,Object結構和Set結構的寫法不一樣。code

//對象的寫法
const properties ={
    'width':1,
    'height':1
};
if(properties[someName]){
    //do something
}
//Set的寫法
const properties = new Set();
properties.add('width');
properties.add('height');
if(properties.has(someName)){
    //do something
}

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]

遍歷操做

Set 結構的實例有四個遍歷方法,能夠用於遍歷成員。ip

-keys():返回鍵名的遍歷器。
-values():返回鍵值的遍歷器。
-entries():返回鍵值對的遍歷器。
-forEach():使用回調函數遍歷每一個成員。

(1)keys(),value(),entries()
keys方法、values方法、entries方法返回的都是遍歷器對象。因爲Set結構沒有鍵名,只有鍵值因此keys方法和values方法的行爲徹底一致。element

let set = new Set(['red','green','blue']);
for(let item of set.keys){
    console.log(items);//red,grren,blue
}
for(let item of set.values){
    console.log(item);//red,green,blue
}
for(let item of set.entries){
    console.log(item)
}
//['red','red']['green','green']['blue','blue']

上面代碼中,entries方法返回的遍歷器,同時包括鍵名和鍵值,因此每次輸出一個數組,它的兩個成員徹底相等。
Set結構的實例默承認遍歷,它的默認遍歷器生成函數就是它的values方法。

Set.prototype[Symbol.iterator] === Set.prototype.values

這就意味着,能夠省略values方法,直接用for...of循環遍歷Set。

let set = new Set(['red','green','blue']);
for(let x of set){
    console.log(x);
}
//red green blue

(2)forEach()
Set結構的實例與數組同樣,也擁有forEach方法,用於對每一個成員執行某種操做,沒有返回值。

let set = new Set([1,4,9]);
set.forEach((value,key)=>console.log(key+':'+value))
//1:1 4:4 9:9

上面代碼說明,foreach方法的參數就是一個處理函數。該函數的參數與數組的forEach一致,依次爲鍵值、鍵名、集合自己。這裏須要注意,Set結構的鍵名就是鍵值,所以第一個參數與第二個參數的值永遠都是同樣的。另外,forEach方法還能夠有第二個參數,表示綁定處理函數內部的this對象。
(3)遍歷的應用
擴展運算符(...)內部使用for...of循環,因此也可使用Set結構。

let set = new Set(['red','green','blue']);
let arr = [...set];
//['red','green','blue']
擴展運算符和Set結構相結合,就能夠去除數組的重複成員。
let arr = [3,5,2,2,5,5];
let unique = [...new Set(arr)]
//[3,5,2]

並且,數組的map和filter方法也能夠間接用於Set了。

let set = new Set([1,2,3]);
set = new Set([...set].map(x=x>*2));
//返回set結構:{2,4,6}

let set = new Set([1,2,3,4,5]);
set = new Set([...set].filter(x=>(x%2)==0));
//返回Set結構:{2,4}

所以使用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}

Map含義和基本用法

Javascript的對象,本質上是鍵值對的集合,可是傳統上只能用字符串看成鍵,這給它的使用帶來了很大的限制。

const data = {};
const element = document.getElementById('myDiv');
data[element] = 'metadata';
data['[object HTMLDivElement]']//'metadata'

上面代碼原意是將一個DOM節點做爲對象data的鍵,可是因爲對象只接受字符串做爲鍵名,因此element被自動轉爲字符串[object HTMLDivElement].
爲了解決這個問題,ES6提供了Map數據結構。他相似與對象,也是鍵值對的集合,可是鍵的範圍不限於字符串,各類類型的值均可以看成鍵。也就是說,Object結構提供了字符串-值的對應,Map結構提供了值-值的對應,是一種更完善的Hash結構實現。若是你須要鍵值對的數據結構,Map比Object更合適。

const m = new Map();
const o = {p:'Hello World'};
m.set(o,'content');
m.get(o)//'content'
m.has(o)//true
m.delete(o)//true
m.has(o)//false

上面代碼使用Map結構set方法,將對象o看成m的一個鍵,而後又使用get方法讀取這個鍵,接着使用delete方法刪除這個鍵。
上面的例子展現瞭如何向Map添加成員。做爲構造函數,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

事實上,不只僅是數組,任何具備Iterator接口、每一個成員都是一個雙元素的數組的數據結構都剋以看成Map構造函數的參數。也就是說,Set和Map均可以用來生成新的Map。

const set = new Set([
    ['foo',1],
    ['bar',2]
])
const m1 = new Map(set);
m1.get('foo')//1

const m2 = new Map([['baz',3]]);
const m3 = new Map(m2);
m3.get('baz')//3

上面代碼中,咱們分別使用set對象和Map對象,看成Map構造函數的參數,結果都生成了新的Map對象。
若是對同一個鍵屢次賦值,後面的值將覆蓋前面的值。

const map = new Map();
map.set(1,'aaa')
   .set(1,'bbb')
map,get(1)//'bbb'

上面代碼對鍵1連續賦值兩次,後一次的值覆蓋前一次的值。
若是讀取一個未知的鍵,則返回undefined。

new Map().get('dsada')//undefined.

實例的屬性和操做方法

(1)size屬性
size屬性返回Map結構的成員總數。

const map = new Map()
map.set('foo',true)
map.set('bar',false)
map.szie//2

(2)set(key,value)
set方法設置鍵名key對應的鍵值爲value,而後返回整個map結構。若是key已經有值,則鍵值會被更新,不然就新生成該鍵。

const m = new Map()
m.set('edition',6);//鍵是字符串
m.set(262,'standard');//鍵是數值
m.set(undefined,'nah');//鍵是undefined

set方法返回的是當前的Map對象,所以剋以採用鏈式寫法。

let map = new Map()
    .set(1,'a')
    .set(2,'b')
    .set(3,'c')

(3)get(key)
get方法讀取key對應的鍵值,若是找不到key,返回undefined。

const m = new Map();
const hello = function(){console.log('hello');};
m.set(hello,'Hello ES6')//鍵是函數
m.get(hello)//Hello ES6

(4)has(key)
has方法返回一個布爾值,表示某個鍵是否在當前Map對象之中。

const m = new Map();
m.set('edition',6);
m.set('262','standard');
m.set(undefined,'nah');
m.has('edition')//true

(5)delete(key)
delete方法刪除某個鍵,返回true,若是刪除失敗,返回false。

const m = new Map();
m.set(undefined,'nah');
m.has(undefined)//true
m.delete(undefined);
m.has(undefined);//false

(6)clear()
clear方法清除全部成員,沒有返回值。

let map = new Map();
map.set('foo',true);
map.set('bar',false);
map.size//2
map.clear();
map.size//0;
相關文章
相關標籤/搜索