Set和Map 数据结构
Set
和Map
是数据结构,不是数据类型ES6 提供了新的数据结构
Set
。它类似于数组,但Set
里的值都是唯一的Set
本身是一个构造函数,用来生成Set 数据结构
Set
的实例(myset)
的属性和方法- 属性
myset.size
:返回 Set 结构的成员总数
- 方法
myset.add(val)
:添加某个值,返回 Set 结构本身myset.delete(val)
:删除某个值,返回一个布尔值,表示删除是否成功myset.has(val)
:返回一个布尔值,表示该值是否为Set
的成员myset.clear()
:清除所有成员,没有返回值myset.forEach((val, key, set) => {})
:使用回调函数遍历每个成员- 第一二个的参数
val 和 key
是一样的,set
是set集合本身
- 第一二个的参数
myset.keys()
:返回键名的遍历器myset.values()
:返回键值的遍历器myset.entries()
:返回键值对的遍历器 ```javascript // 案例一 const myset = new Set();
- 属性
let s1 = Symbol();
// 增加元素 myset.add(1); myset.add(1); // 重复了,自动过滤 myset.add({}).add(s1); console.log(myset.size); // 3
// 删除元素 myset.delete(1); console.log(myset.has(s1)); // true
// 清空元素 myset.clear();
```javascript
// 案例二:new Set() 如何传参
// 参数是带有[Symbol.iterator]属性的对象即可
let s1 = new Set([4, 5, 6]);
let s2 = new Set(document.childNodes);
(function () {
let s3 = new Set(arguments);
})(4, 5, 6)
// 案例三:关于set的遍历
let set = new Set(['red', 'green', 'blue']);
for (let item of set.keys()) {
console.log(item);
}
// red
// green
// 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"]
// Set 结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法
Set.prototype[Symbol.iterator] === Set.prototype.values // true
// 所以有
for (let item of set) {
console.log(item)
}
// red
// green
// blue
Set的简单应用
// 数组去重
let arr = [1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 7];
arr = [...new Set(arr)]; // [1,2,3,4,5,6,7]
// 实现交、并、差
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 交集
let intersect = new Set([...a].filter(item => b.has(item)))
// 并集
let union = new Set([...a, ...b]);
// (a 相对于 b 的)差集
let difference = new Set([...a].filter(item => !b.has(item)))
WeakSet
- WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别
- WeakSet 的成员只能是对象,不能是其他类型的值
- WeakSet 中的对象(非值类型)都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用
WeakSet
的实例(myweakSet)
的属性和方法- 属性
myweakSet
没有myweakSet.size
这个属性
- 方法
myweakSet.add(val)
:添加某个值,返回 Set 结构本身myweakSet.delete(val)
:删除某个值,返回一个布尔值,表示删除是否成功myweakSet.has(val)
:返回一个布尔值,表示该值是否为Set
的成员
- 应用
- WeakSet 的一个用处,是储存 DOM 节点,而不用担心这些节点从文档移除时,会引发内存泄漏 ```javascript // 案例一:成员只能是对象 let myweakSet = new WeakSet(); let arr = [1, 2, 3]; let obj = { name: ‘foo’ }; let str2 = new String(‘good’); myweakSet.add(arr); // 通过 myweakSet.add(obj); // 通过 myweakSet.add(str1); // 报错 myweakSet.add(str2); // 通过
- 属性
myweakSet.delete(arr)
console.log(myweakSet);
```javascript
// 案例二:弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用
let myweakSet = new WeakSet();
myweakSet.add([1, 2, 3]);
myweakSet.add({ name: 'foo' });
myweakSet.add(new String('good'));
console.log(myweakSet); // 空的Set。[[Entries]]里面什么都没有
/**
* 由于[1, 2, 3]、{ name: 'foo' }、new String('good')
* 没有像案例一,赋值给一个变量,没有被某个变量引用
* 执行完add函数后,由于没有被变量引用。浏览器的垃圾回收机制又不考虑WeakSet的引用
* 根据浏览器的垃圾回收机制,内存被回收了
* 所以myweakSet里面的东西,就找不到了
*/
Map
Map的介绍
- ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键
- 如果需要“键值对”的数据结构,Map 比 Object 更合适
Map
的实例(myMap)
的属性和方法- 属性
myMap.size
:返回 Map 结构的成员总数
- 方法
myMap.set(key,value)
:该方法设置键名key
对应的键值为value
,然后返回整个 Map 结构- 如果key已经有值,则键值会被更新,否则就新生成该键
myMap.get(key)
:该方法读取key
对应的键值,如果找不到key
,返回undefined
myMap.has(key)
:该方法返回一个布尔值,表示某个键是否在当前 Map 对象之中myMap.delete(key)
:该方法删除某个键,返回true
。如果删除失败,返回false
myMap.clear()
:该方法清除所有成员,没有返回值myMap.keys()
:返回键名的遍历器myMap.values()
:返回键值的遍历器myMap.entries()
:返回所有成员的遍历器myMap.forEach()
:遍历 Map 的所有成员 ```javascript // 案例一 let myMap = new Map();
- 属性
let obj = { name: 2 }; let sym = Symbol(); // 添加键值对 myMap.set(‘good’, true) myMap.set(obj, { age: 18 }).set(sym, 456);
// 获取key对应value myMap.get(sym); // 456
// 判断是否含有obj这个key myMap.has(obj); // true
// 找到对应的key,删除key-value myMap.delete(sym); // true
console.log(myMap.size); // 2
// 清空所有成员 myMap.clear();
console.log(myMap.size); // 0
```javascript
// 案例二:new Map() 如何传参
// 参数可以是任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构
// 传参:数组
let m1 = new Map([
[{ name: 'Kery' }, { age: 18 }],
[456, 'good-one'],
[Symbol(), 'pointSystem']
])
// 传参:set集合
let set = new Set();
document.head.childNodes.forEach((item, index) => set.add([index, item]))
let m2 = new Map(set);
// 传参:map集合
let m3 = new Map(m1);
// 案例三:关于Map的遍历
let map = new Map([
[1, 55],
['good', 123],
[{}, 555]
])
Map数据结构与其他数据结构的互相转换
- Map 与 数组 ```javascript // 数组 转 Map let map = new Map([ [1, 55], [‘good’, 123], [{}, 555] ])
// Map 转 数组 let arr = […map]; // [[1, 55], [‘good, 123], [{}, 555]]
- Map 与 对象
```javascript
// 对象 转为 Map
// 可以通过Object.entries()
let obj = { a: 1, b: 2 };
let map = new Map(Object.entries(obj));
// Map 转为 对象
function strMapToObj(strMap) {
let obj = Object.create(null);
for (let [k,v] of strMap) {
obj[k] = v;
}
return obj;
}
let obj2 = strMapToObj(map);
- Map 与 JSON
- Map 转 JSON
- 一种情况是,Map 的键名都是字符串,这时可以选择转为对象 JSON。
- 另一种情况是,Map 的键名有非字符串,这时可以选择转为数组 JSON
- JSON 转 Map
- 一种情况是,所有键名都是字符串
- 另一种情况是,整个 JSON 就是一个数组,且每个数组成员本身,又是一个有两个成员的数组 ```javascript // JSON 转成 Map let json1 = JSON.stringify({ a: [456], b: 2 }); let json2 = JSON.stringify([[true, 123], [{ foo: 3 }, [‘abc’]]]);
- Map 转 JSON
function jsonToMap(json) { let tmp = JSON.parse(json); let type = Object.prototype.toString.call(tmp).slice(8, -1); let map = null; if (type === ‘Object’) { map = new Map(Object.entries(tmp)); } else if (type === ‘Array’) { map = new Map(tmp); } return map }
let map = jsonToMap(json1);
// Map 转 JSON let map1 = new Map([ [‘a’, 123], [13, { name: ‘jack’ }] ]);
let map2 = new Map([ [new Date(), 1], [{ age: 18 }, 55], [Symbol(), 66] ])
function mapToJSON(map) { let keys = […map.keys()]; let check = keys.every(key => [‘Number’, ‘String’].includes(Object.prototype.toString.call(key).slice(8, -1)) ) if (check) { let obj = Object.create(null); map.forEach((val, key) => { obj[key] = val }) return JSON.stringify(obj); } return JSON.stringify([…map]); }
let json = mapToJSON(map2); ```
WeakMap
WeakMap
结构与Map
结构类似,也是用于生成键值对的集合。但,它与**Map**
有两个区别- WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名
- WeakMap 中的对象(非值类型)都是弱引用,即垃圾回收机制不考虑 WeakMap 对该对象的引用
WeakMap
的实例(myweakMap)
的属性和方法- 属性
myweakMap
没有myweakMap.size
这个属性
- 方法
myweakMap.set(key, val)
:添加键值对,返回 Map 结构本身myweakMap.has(key)
:返回一个布尔值,表示该值是否为Map
的成员myweakMap.get(key)
:返回 key 对应的值myweakMap.delete(key)
:删除 key 那个键值对
- 应用
- 是储存 DOM 节点,而不用担心这些节点从文档移除时,会引发内存泄漏
- 属性