Set和Map数据结构
本系列属于阮一峰老师所著的ECMAScript 6 入门学习笔记
Set
类似数组,但是成员的值都是唯一的没有重复的值,Set
本身是一个构造函数,用来生成Set
数据结构
const s = new Set()
[2,3,4,5,2,3,2].forEach(x => s.add(x))
for(let i of s){
console.log(i)
}
// 2,3,4,5
const set = new Set([1,2,3,4,4])
[...set] // [1,2,3,4]
set.size // 4
//向Set中加入值的时候,不会发生类型转换,5与'5'是两个值,判断值是否相等类似===,区别是NaN等于自身
const set = new Set([NaN,NaN]) // Set(1) {NaN}
//两个对象总是不相等的
const set = new Set([{},{}]) // Set(2) {{...},{...}}
有以下属性:
Set.prototype.constructor
:构造函数,默认是Set
函数Set.prototype.size
:返回Set
实例的成员总数有以下方法:
add(value)
:添加某个值,返回Set
结构本身delete(value)
:删除某个值,返回布尔值,表示删除是否成功has(value)
:返回一个布尔值,表示该值是否为Set
的成员clear()
:清除所有成员,无返回值s.add(1).add(2).add(2)
s.size // 2
s.has(1) // true
s.has(3) // false
s.delete(2) // true
// Array.from方法可以将Set结构转为数组
const items = new Set([1,2,3,4,5])
const array = Array.from(items) // [1,2,3,4,5]
// 利用Set去重
function dedupe(array){
return Array.from(new Set(array))
}
有以下四种遍历方法,遍历顺序就是插入顺序:
keys()
:返回键名values()
:返回键值entries()
:返回键值对forEach()
:使用回调函数遍历每个成员let set = new Set(['red','green','blue'])
// Set结构默认的遍历器生成函数就是values,所以遍历value时可以直接省略values方法直接遍历
Set.prototype[Symbol.iterator] === Set.prototype.values // tue
for(let x of set){
console.log(x)
}
// red green blue
set.forEach((value,key) => console.log(key + ':' + value))
// red:red green:green blue:blue
let arr = [...set] // ['red','green','blue']
// 与拓展运算符结合去重
let unique = [..new Set(set)] // ['red','green','blue']
// 结合数组方法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}
// 改变原有Set结构的方法
let set = new Set([1,2,3])
set = new Set([...set].map(val => val*2)) // set {2,4,6}
set = new Set(Array.from(set,val => val*2)) // set {2,4,6}
WeakSet
与Set
类似,区别在于:WeakSet
的成员只能是对象;WeakSet
对象都是弱引用,即垃圾回收机制不考虑WeakSet
对该对象的引用,也就是说如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于WeakSet
中
因此,WeakSet
的成员不适合引用,因为它随时会消失,也不可以遍历
const a = [[1,2],[3,4]]
const ws = new WeakSet(a) // WeakSet {[1,2],[3,4]}
// WeakSet只有add()、delete()、has()三种方法,无size属性,不可遍历,无clear()方法
传统对象键值只能是字符串,Map
提供了一种方法,可以接收键值不仅为字符串,提供"值-值"对应的结构
// 利用Map结构的set方法,将对象作为键
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
// Map结构接收数组参数
const map = new Map([['name','张三'],['title','Angus']])
map.size // 2
map.has('name') // true
map.get('name') // 张三
// 不仅是数组,所有具有Iterator接口、每个成员都是一个双元素的数组数据结构都可以作为Map函数的参数
const set = new Set([['foo',1],['bar',2]])
const m1 = new Map(set)
m1.get('foo') // 1
// 对一个键多次赋值,后面的值将会覆盖前面的值
const map = new Map()
map.set(1,'1').set(1,'2')
map.get(1) // '2'
const map = new Map()
map.set('foo',true).set('bar',false)
map.size // 2
map.get('foo') // true
map.has('foo') // true
map.delete('foo') // true
map.clear()
const map = new Map([['F','no'],['T','yes']])
// keys()方法
for(let key of map.keys()){
console.log(key) // 'F' 'T'
}
// values()方法
for(let value of map.values()){
console.log(value) // 'no' 'yes'
}
// entries()方法
for(let item of map.entries()){
console.log(item) // ['F','no'] ['T','yes']
}
// Map结构默认的遍历器接口就是entries()方法
[...map] // [['F','no'],['T','yes']]
// 结合数组的map和filter方法,实现Map的遍历和过滤
const map = new Map().set(1,'a').set(2,'b')
const map1 = new Map([...map].filter(([k,v]) => k<3)) // Map(2) {1=>'a',2=>'b'}
const map2 = new Map([...map].map(([k,v]) => [k*2,'_'+v])) // Map(2) {2=>'_a',4=>'_b'}
// forEach方法
map.forEach(function(value, key, map) {
console.log("Key: %s, Value: %s", key, value); // Key:1,Value:a Key:2,Value:b
});
// forEach接收第二个参数用来绑定this
const reporter = {
report: function(key,value){
console.log('Key:%s,Value:%s',key,value)
}
}
map.forEach(function(value,key,map){
this.report(key,value) // Key:1,Value:a Key:2,Value:b
},reporter)
WeakMap
与Map
类似,但有两点区别:WeakMap
只接收对象作为键名;WeakMap
键名所指向的对象,不计入垃圾回收机制,这一点与WeakSet
相同。
WeakMap
不能使用size
属性,不能遍历,也不支持clear
。
可用方法有get()
、set()
、has()
、 delete