一、Set(集合):
Set是一种在ES6中新增的数据结构,与数组不同的是其成员无重复且无序。
与Array一样,Set本身也是一个构造函数,可以从其身上new出新对象。
Set常用属性及增删改查方法:
- size属性: 返回集合的元素个数。(类似数组的长度length)
- add(value)方法: 向集合中添加一个元素value。注意:如果向集合中添加一个已经存在的元素,不报错但是集合不会改变。
- delete(value)方法: 从集合中删除元素value。
- has(value)方法: 判断value是否在集合中,返回true或false.
- clear()方法: 清空集合。
用法如下:
let mySet = new Set([1, 2, 3, 2, 1]);
console.log(mySet.size); //3
console.log(...mySet); //1,2,3
mySet.add(4);
console.log(mySet.size); //4
mySet.delete(3);
console.log(mySet.size); //3
console.log(mySet.has(2)); //true
mySet.clear();
console.log(mySet.size); //0
将Set转为数组:
Array.from 方法可以将 Set 数据结构转为数组:
let mySet = new Set([1, 2, 3, 2, 1]);
console.log(mySet instanceof Array); //false
let myArr = Array.from(mySet);
console.log(myArr instanceof Array); //true
console.log(myArr); // [1,2,3]
Set集合遍历方法:
注意:遍历顺序为插入顺序
- keys():返回一个包含集合中所有键的迭代器
- values():返回一个包含集合中所有值得迭代器
- entries():返回一个包含Set对象中所有元素得键值对迭代器
- forEach(callbackFn, thisArg):用于对集合成员执行callbackFn操作,如果提供了 thisArg
参数,回调中的this会是这个参数,没有返回值
let mySet = new Set([1, 2, 3, 2, 1]);
console.log(mySet.keys());// SetIterator {1, 2, 3}
console.log(mySet.values());// SetIterator {1, 2, 3}
console.log(mySet.entries());// SetIterator {1, 2, 3}
mySet.forEach(function(i){
console.log(i+this); // 11,12,13
},10)
二、WeakSet:
WeakSet 与 Set 的区别:
- WeakSet只能存放对象引用,而Set可以存放任何类型的值。
- WeakSet 对象中储存的对象值都是被弱引用的,即垃圾回收机制不考虑 WeakSet对该对象的应用,如果没有其他的变量或属性引用这个对象值,则这个对象将会被垃圾回收掉(不考虑该对象还存在于 WeakSet中),运行前后成员个数可能会不一致,遍历结束之后,有的成员可能取不到了(被垃圾回收)。
- 其clear()方法不可用。
- WeakSet对象是无法被遍历的(ES6 规定 WeakSet 不可遍历),也没有办法拿到它包含的所有元素
- 其余无差别。
三、Map(字典):
集合与字典的区别:
- 同: 集合和字典都是存储不重复的值.
- 异: 集合中是以[value,value]存储的,字典中是以[key,value]存储的。
任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构都可以当作Map构造函数的参数,如下:
let Arr = [["name","jack"],["age","18"],["sex","man"]];
let myMap = new Map(Arr);
console.log(myMap.get("name")); //jack
如果传入的数组Key出现同名,键值将会被最后一个此键名的值的所覆盖,如:
let Arr = [["name","jack"],["name","Mary"],["age","18"],["sex","man"]];
let myMap = new Map(Arr);
console.log(myMap.get("name")); //Mary
特别注意: 只有对同一个对象的引用,Map 结构才将其视为同一个键。
let Arr = [[["name"],"jack"]];
let myMap = new Map(Arr);
console.log(myMap.get(["name"])); //两个["name"]在内存中的地址不一样,此处输出undefined;
这样做就没问题:
let arr1 = ["name"];
let Arr = [[arr1,"jack"]];
let myMap = new Map(Arr);
console.log(myMap.get(arr1)); //输出jack;
Map常用属性及增删改查方法:
- size: 属性,取出字典的长度
- set(key, value):方法,向字典中添加新元素
- get(key):方法,通过键查找特定的数值并返回
- has(key):方法,判断字典中是否存在键key
- delete(key):方法,通过键 key 从字典中移除对应的数据
- clear():方法,将这个字典中的所有元素删除
用法如下:
let myMap = new Map();
myMap.set("name","Jack");
myMap.set("age","18"); //添加元素
console.log(myMap.size); //2
console.log(myMap.get("name"));//Jack
console.log(myMap.has("name")); //true
myMap.delete("age"); //删除
console.log(myMap.size); //1
console.log(myMap.has("age")); //false
myMap.clear(); //清空元素
console.log(myMap.size); //0
Map常用遍历方法:
- Keys():将字典中包含的所有键名以迭代器形式返回
- values():将字典中包含的所有数值以迭代器形式返回
- entries():返回所有成员的迭代器
- forEach():遍历字典的所有成员
Map.forEach:
let myMap = new Map();
myMap.set("name","Jack");
myMap.set("age","18");
myMap.set("sex","man");
myMap.forEach(
(value,key,map)=>{
console.log(value); //Jack,18,man
console.log(key); //name,age,sex
console.log(map); //自身,自身,自身
}
)
Map转数组:
用展开运算符:
let myMap = new Map();
myMap.set("name","Jack");
myMap.set("age","18");
myMap.set("sex","man");
console.log(...myMap); // [["name","Jack"],["age","18"],["sex","man"]];
四、WeakMap:
WeakMap与Map的区别:
WeakMap 对象是一组键值对的集合,其中的键是弱引用对象,而值可以是任意。
注意,WeakMap 弱引用的只是键名,而不是键值。键值依然是正常引用。
WeakMap 中,每个键对自己所引用对象的引用都是弱引用,在没有其他引用和该键引用同一对象,这个对象将会被垃圾回收(相应的key则变成无效的),所以,WeakMap 的 key 是不可枚举的。
方法:
- has(key):判断是否有 key 关联对象
- get(key):返回key关联对象(没有则则返回 undefined)
- set(key):设置一组key关联对象
- delete(key):移除 key 的关联对象
用法与Map一致。
五、总结:
Set:
- 成员唯一、无序且不重复
- [value, value],键值与键名是一致的(或者说只有键值,没有键名)
- 可以遍历,方法有:add、delete、has
WeakSet:
- 成员都是对象
- 成员都是弱引用,可以被垃圾回收机制回收,可以用来保存DOM节点,不容易造成内存泄漏
- 不能遍历,方法有add、delete、has
Map:
- 本质上是键值对的集合,类似集合
- 可以遍历,方法很多可以跟各种数据格式转换
WeakMap:
- 只接受对象作为键名(null除外),不接受其他类型的值作为键名
- 键名是弱引用,键值可以是任意的,键名所指向的对象可以被垃圾回收,此时键名是无效的 不能遍历,方法有get、set、has、delete