一:Set
-
ES6提供了新的数据结构
Set
。它类似于数组,但是成员的值是唯一的,没有重复的值。 -
Set
是一个构造函数,用来生成Set
数据结构。 -
向
Set
加入值的时候,是不会发生类型转换,例如:5
和"5"
是两个不同的值。注意:向Set
加入值时,NaN
等于自身。
Set
实例的属性和方法
属性:
Set.prototype.constructor
:构造函数,默认就是Set
函数Set.prototype.size
:返回Set
实例的成员总数
方法:
Set.prototype.add(value)
:添加某个值,返回Set
结构本身Set.prototype.delete(value)
:删除某个值,返回一个布尔值,表示删除是否成功Set.prototype.has(value)
:返回一个布尔值,表示该值是否为Set
的成员Set.prototype.clear()
:清除所有成员,没有返回值
注意:Array.from
方法可以将Set
结构转为数组(实现数组去重)
Set
结构的遍历操作
有四个遍历方法,可以用于遍历成员:
Set.prototype.keys()
:返回键名的遍历器Set.prototype.values()
:返回键值的遍历器Set.prototype.entries()
:返回键值对的遍历器Set.prototype.forEach()
:使用回调函数遍历每个成员
注意:
Set
的遍历顺序就是插入的顺序。- 由于
Set
结构没有键名,只有键值,所以keys
方法和values
方法的行为完全一致 Set
结构的实例默认可遍历,它的默认遍历器生成函数就是它的values
方法
这表示,可以使用Set.prototype[Symbol.iterator] == Set.prototype.values
for...of
循环遍历Set
- 也可以使用
forEach()
let set = new Set([1,2,3]); set.forEach((value,key) => console.log(key+':'+value)) // 1 // 2 // 3
各种遍历的应用
- 扩展运算符
...
- 数组的
map
和filter
方法可以间接用于Set
- 在遍历操作中改变原来的
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
二:WeakSet
-
WeakSet
是一个构造函数,可以使用new
命令来创建WeakSet
数据结构 -
WeakSet
可以接受一个数组或类似数组的对象作为参数(任何具有Iterable
接口的对象,都可以作为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); // Uncaught TypeError: Invalid value used in weak set(…)
注意:是a
数组的成员为WeakSet
的成员,而不是a
数组本身。意味着,数组的成员只能是对象。
WeakSet
结构有以下三个方法:
WeakSet.prototype.add(value)
:向WeakSet
实例添加一个新成员WeakSet.prototype.delete(value)
:清除WeakSet
实例的指定成员WeakSet.prototype.has(value)
:返回一个布尔值,表示某个值是否在WeakSet
实例之中
注意:
WeakSet
没有size
属性,没有办法遍历它的成员
WeakSet
不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保证成员的存在。WeakSet
的一个用处,是存储DOM
节点,而不用担心这些节点从文档移除时,会引发内存泄漏。
这里使用const foos = new WeakSet() class Foo{ constructor(){ foods.add(this) } method(){ if(!foos.has(this)){ throw new TypeError('Foo.prototype.method 只能在Foo的实例上调用!') } } }
WeakSet
的好处:foos
对实例的引用,不会被计入内存回收机制,所以删除实例的时候,不用考虑foos
,也不会出现内存泄漏
三:Map
- ES6提供了
Map
数据结构,它类似于对象,也是键值对的集合,但是键的范围不限于字符串,各种类型的值(包括对象)都可以当作键。 Object
提供了字符串-值
的对应,但是Map
结构提供了值-值
的对应,是一种更完善的Hash
结构实现。Map
可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。const map = new Map([ ['name','小白'], ['title','小红'] ]); map.size // 2 map.has('name') // true map.get('name') // "小白" map.has('title') // true map.get('title') // "小红"
Map
构造函数接受数组作为参数,实际山执行的是下面的算法:const items = [ ['name','小白'], ['title','小红'] ]; const map = new Map(); items.forEach( ([key,value]) => map.set(key,value) );
- 任何具有
Iterator
接口,且每个成员都是一个双元素的数组的数据结构都可以当作Map
构造函数的参数。也就是说Set
和Map
都是可以用来生成新的Map
- 如果对同一个键多次赋值,后值会覆盖前值
注意:
- 只有对同一个对象的引用,
Map
结构才将其视为同一个键。
上述,实际上是俩个不同的数组实例,内存地址不一致。const map = new Map(); map.set(['a'],123); map.get(['a']); // undefined
Map
的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键(解决了同名属性碰撞的问题) - 如果
Map
的键是一个简单类型的值(数字,字符串,布尔值),只要两个值严格相等,Map
将其视为一个键:0
和-0
就是一个键,虽然NaN
不严格等于自身,但Map
将其视为同一个键。
Map
结构的属性和方法如下
size
属性:返回Map
结构的成员总数Map.prototype.set(key,value)
set
方法设置键名key
对应的键值为value
,然后返回整个Map
结构,如果key
已经有值,则会被覆盖。
set
方法返回的是当前的Map
对象,因此可以采用链式写法let map = new Map() .set(1,'a') .set(2,'b') .set(3,'c');
Map.prototype.get(key)
get
方法读取key
对应的键值,找不到则返回undefined
Map.prototype.has(key)
has
方法返回一个布尔值,表示某个键是否在当前的Map
对象之中Map.prototype.delete(key)
delete
方法删除某个键,返回true
。失败,返回false
Map.prototype.clear()
clear
方法清除所有的成员,没有返回值
Map
的遍历方法:
Map.prototype.keys()
:返回键名的遍历器Map.prototype.values()
:返回键值得遍历器Map.prototype.entries()
:返回所有成员的遍历器Map.prototype.forEach()
:遍历Map
的所有成员
注意:
Map
的遍历顺序就是插入顺序Map
结构的默认遍历器接口(Symbol.iterator
属性),就是entries
方法map[Symbol.iterator] === map.entries
Map
结构转为数组结构,比较快速的方法是使用扩展运算符(...
)- 结合数组的
map
方法,filter
方法,可以实现Map
的遍历和过滤(Map本身没有map
和filter
方法) Map
有一个forEach
方法,于数组的forEach
方法类似,也可以实现遍历
Map与其他数据结构的互相转换
Map
转为数组- 数组转为
Map
Map
转为对象- 对象转为
Map
Map
转为JSON
JSON
转为Map
四:WeakMap
WeakMap
结构与Map
结构类似,也是用于生成键值对的集合
WeakMap
与Map
的区别有两点:
WeakMap
只接受对象作为键名(null
除外),不接受其他类型的值作为键名WeakMap
的键名所指向的对象,不计入垃圾回收机制。
即,一旦不再需要,WeakMap
里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。
例如:在网页的DOM
元素上添加数据,就可以使用WeakMap
结构,当该DOM
元素被清除,其所对应的WeakMap
记录就会自动被移除。
注意:WeakMap
弱引用的只是键名,而不是键值,键值依然是正常引用
WeakMap
与Map
在API上的区别主要两个:
- 没有遍历操作:即,没有
keys()
,values()
,entries()
方法,也没有size
属性。 - 无法清空,即,不支持
clear
方法。因此,WeakMap
只有四个方法可用:get()
,set()
,has()
,delete()