Set 和 Map 是 ES6 新增的数据结构。成员的值都是唯一的、无重复的。
1、Set 元素唯一
Set 对象是值的集合,且元素是唯一的,类比数组。
留意下: 唯一值的判断和 === 的运算符算法是不一样的。原,-0\+0 是相同的。NaN之间视为相同的值,-0 +0
是两个值
consturctor 上的api
- add 返回Set对象,所以可以链式添加 xx.add().add(3) 添加元素
- delete 返回Boolean 结果
- 这里的
entries
返回一个新的迭代器对象,每个键和值相等。 Set.prototype.forEach(callbackFn[, thisArg])
如果提供了thisArg参数,回调中的this会是这个参数。
有迭代器对象的,都可以用for ... of 进行遍历
for (let item of mySet) console.log(item);
// key === value 每个键和值相等
for(let [key, value] of mySet.entries()) console.log(key, value)
set 和Array 的互换
let set = new Set([1,2,3])
[...set] // [1,2,3]
Array.from(set)
求交集、并集、差集, 数组去重
// 交集
let intersection = new Set([...set1].filter(x => set2.has(x)))
let union = new Set([...set1, ...set2])
let difference = new Set([...set1].filter(x => !set2.has(x)))
如果Set 传入一个字符串,则会拆开 //
Array.from(new Set('Hello')) // ['H', 'e', 'l', 'l', 'o']
如何修改?
2、Map 保存键值对,且有插入顺序
Map 对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值) 都可以作为一个键或一个值。 键值相等的判断和set 上是一致的。
Map 和 Object 的比较:
对比选项 | Map | Object | 键名冲突 | Map默认没有显式的键 | 容易与原型的键名产生冲突 | 键的类型 | Map的键可以是任意值,函数、对象或任意基本类型 | object 必须是string 或 symbol | size | 返回键值对数量 | object keys 读取 | 迭代 | Map 是 iterable 的,可以直接被迭代(for...of)。 | for...in or keys遍历 | 性能 | 频繁增删键值对的场景下表现更好 | 无 |
---|
constructor 上的api
- 通过set 给Map对象新增键值。返回Map对象,可链式
let myMap = new Map()
let keyObj = {}
myMap.set(keyObj, '新增键值')
myMap.get(keyObj) // 新增键值
myMap.get({}) // undefined
myMap.get(NaN); // NaN 是一个
// 注意是value key o
myMap.forEach(function(value, key) {
console.log(key + " = " + value);
})
Map与数组的关系
二维数组的形式
let arr = [[key, value], [xiaoming, 12]]
let aMap = new Map(arr)
let arr2 = [...aMap]
console.log(Array.from(aMap.keys))
// Map对象同数组进行合并时,如果有重复的键值,则后面的会覆盖前面的。
let merged = new Map([...arr, ...xxx, [1, 'eins']]);
通过map.set 进行值覆盖。
注意!别为Map设置对象属性,而应该用set
。不然会有意外。
let wrongMap = new Map()
wrongMap['bla'] = 'blaa'
3、WeakSet 只能是对象的集合,不能是任何类型的任意值、无法枚举
WeakSet 对象集合中对象的引用为弱引用,不会被标记引用,容易被垃圾回收。
递归、涉及较多对象时,使用。
垃圾回收案例:
let obj = {name : 'hhh'}
// 如果新增 let array = [obj] 则不会被垃圾回收
// let map = new WeakMap() map.set(obj, '这样也是会被垃圾回收,因为是弱引用')
obj = null // 可以被回收
ECMAScript 6: what is WeakSet for?
案例:
案例1、我们可以将用户添加到 WeakSet 中,以追踪访问过我们网站的用户
let visitedSet = new WeakSet();
let john = { name: "John" };
let pete = { name: "Pete" };
let mary = { name: "Mary" };
visitedSet.add(john); // John 访问了我们
visitedSet.add(pete); // 然后是 Pete
visitedSet.add(john); // John 再次访问
// visitedSet 现在有两个用户了
// 检查 John 是否来访过?
alert(visitedSet.has(john)); // true
// 检查 Mary 是否来访过?
alert(visitedSet.has(mary)); // false
john = null;
// visitedSet 将被自动清理
案例2、
const requests = new WeakSet();
class ApiRequest {
constructor() {
requests.add(this);
}
makeRequest() {
if(!request.has(this)) throw new Error("Invalid access");
// do work
}
}
// 如果没有weakSet ,你可能需要 通过生命周期去管理,手动删除
const requests = new Set();
class ApiRequest {
constructor() {
requests.add(this);
}
makeRequest() {
if(!request.has(this)) throw new Error("Invalid access");
// do work
}
destory(){
requests.delete(this)
}
}
ApiRequest 类中想验证 this 对象的来源,于是需要一个集合来存所有通过构造函数构建的对象,ApiRequest 类却并不像参与到实例对象的生命周期中去,直接用 Set 的话,由于Set 对于实例对象存在引用,就会发生内存泄漏。
案例3、DOM节点作为键名
consturctor 上的api
4、WeakMap 键必须是对象、无法枚举
WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。 Map 的赋值和搜索操作都是O(n)、且容易导致内存泄漏,因为数组会一直引用着每个键和值。
基本上,如果你要往对象上添加数据,即额外数据的存储 又不想干扰垃圾回收机制,就可以使用 WeakMap。
用来存这个对象相关的数据,与数据共存亡:
- 案例1、一个用户对象作为键,其访问次数为值。当一个用户离开时(该用户对象将被垃圾回收机制回收),这时我们就不再需要他的访问次数了
let visitsCountMap = new WeakMap()
// 递归用户来访次数
function countUser(user){
let count = visitsCountMap.get(user) || 0
visitsCountMap.set(user, count + 1)
}
// ? main.js
let john = { name: "John" };
countUser(john); // count his visits
// 不久之后,john 离开了
john = null;
- 案例2、缓存计算的结果
let cache = new WeakMap()
// 与obj 嘻嘻相关的结果
function process(obj){
if(!cache.has(obj)) {
let result = `与obj有关的计算`
cache.set(obj, result)
}
return cache.get(obj)
}
// other.js
let obj = {}
let result1 = process(obj)
let result2 = process(obj)
obj = null // 如果是Map 就cache 里不可被回收
案例3、DOM节点作为键名
consturctor 上的api
小汇:
- Set 类似于数组,成员值唯一。
- WeakSet 类似 Set,但成员只能是对象,且没有遍历操作。不引用后会被自动回收。
- Map 类似于对象,key值不限于字符串,成员值唯一。
- WeakMap 类似 Map,但只接受对象作为键名(null除外),且没有遍历操作。不引用后会被回收。
MDN
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!