Set集合
Set类型是一种有序列表,其中的值不能重复。
方法和属性
- 调用
new Set()
创建Set集合,Set构造函数的参数是可迭代对象,初始化时会过滤掉重复的值。 - 调用其
add
方法添加元素,当使用 add 添加重复的值,后面的添加会被忽略。 - 使用其
size
属性获取元素数量。 has
方法可用于检测Set集合中是否存在某值。- 调用
delete
方法移除某个元素,clear
方法移除所有元素。 - 使用
forEach
遍历Set集合,只是callback前两个参数(index/item)是相同的。
转换数组
适合用于数组去重的操作。
// 数组转Set,直接传入Set构造函数
let set = new Set([4, 2, 3, 3]);
// Set转数组,使用展开运算符
let array = [...set]
Weak Set集合
将对象存储在Set实例与存储在变量中一样,只要在Set实例中的引用存在,垃圾回收机制就不能释放该对象的内存空间,普通的Set集合就是一种强引用。
let set = new Set(),
key = {name:'phoeny'};
set.add(key);
key = null;
set存放的其实是对象的引用,当执行 key = null
的时候,是切断了key这个变量名和对象之间的联系,但是set中的值和对象之间的引用仍然存在。所以在垃圾回收的时候,这个对象仍是有引用指向的,就不会被回收。
在大部分的情况,强引用Set是我们希望得到的。但在有些情况我们会希望,如果其他引用都不存在了,就让Set集合中的引用也消失。
- WeakSet集合使用 WeakSet 构造函数创建,构造函数的参数是可迭代对象。
- WeakSet只支持3个方法:
add/has/delete
。 - 如果WeakSet中的弱引用是对象的唯一引用,则对象会被回收并释放相应内存。
- 如果 WeakSet 构造函数的参数包含非对象值则会报错,因为它不接收任何原始值。
let set = new WeakSet(),
key = {name:'phoeny'};
set.add(key);
// 虽然看不出有什么不同,但稍后垃圾回收机制运行的时候,会将对象回收的
key = null;
如果你只需要跟踪对象引用,推荐使用 WeakSet 集合,而不是普通 Set 集合。
Map集合
Map 类型是一种存储许多键值对的有序列表。
对象的属性名总会被强制转换为字符串,所以数字5和字符串'5'会当初一个属性,但是Map中是使用Object.is()判断键名的,所以它们会被作为两个独立的键名存在。
在对象中,无法使用对象作为键名,但Map可以。
创建Map
调用 new Map()
创建Map集合,传入的参数也是数组,数组中的每一项是一个两元素数组,第一个元素是键名,第二个元素是键值。
let map = new Map([ ['name','Nicholas'], ['age',25] ])
方法和属性
- 调用其
set
方法传入键名和键值,get
方法通过键名获取键值。 - 使用其
size
属性获取键值对数量。 has
方法可用于检测Map集合中是否存在指定键名。- 调用
delete
方法移除某个键值对,clear
方法移除所有键值对。 - 使用
forEach
遍历Map集合。
Weak Map集合
WeakSet 是弱引用的 Set集合,WeakMap 是弱引用的 Map集合。WeakMap 类型是一种存储许多键值对的无序列表。
WeakMap的键名必须是一个对象,如果使用非对象会报错。WeakMap 的弱引用是针对键名的,键值如果是对象则还是保存的是对象的强引用。如果除了 WeakMap 中键名的弱引用之外,没有其他强引用,那么这个对象会被垃圾回收,同时移除 WeakMap 中的键值对。
WeakMap 只支持4个方法:get/set/has/delete
。
WeakMap 多用于存储DOM元素,也可以存储对象实例的私有数据。
私有数据
在es5中我们会使用闭包来模拟私有数据:
// 只能通过 getName 方法获取 _name 属性,不能直接访问
var Person = (function () {
var privateDate = {},
privateId = 0;
function Person(name) {
// 避免在外面重写 _id 属性
Object.defineProperty(this,'_id',{
value: privateId++,
writable:false
})
privateDate[this._id] = {
name: name
}
}
Person.prototype.getName = function () {
return privateDate[this._id].name;
};
return Person;
}());
let person = new Person('phoeny');
person.getName(); // phoeny
person.name; // undefined
person._id; // 0
利用es6中的WeakMap:
let Person = (function(){
let privateDate = new WeakMap();
function Person(name){
privateDate.set(this,{name:name});
}
Person.prototype.getName = function(){
return privateDate.get(this).name;
}
return Person;
}());
let person = new Person('phoeny');
person.getName()
person._name