1.set集合和map集合
ES6中新增的数据存储结构,不同的场景使用不同的集合去存储数据。
2 set集合
1 创建
用于存储不重复的数据
创建set集合
```js
const s1 = new Set(iterable)
console.log(s1)
```
2 方法
实例方法:
- add() 添加数据
- has() 判断数据是否存在
- delete() 删除数据,返回值为是否删除成功
- clear() 清空集合
- size 集合长度 只读
- for…of forEach
根据set自己仿写set集合
class MySet{
constructor(iterator = []){
// 传递的内容必须是一个可迭代对象
if(typeof iterator[Symbol.iterator] !== "function"){
throw new TypeError(`您所提供的${iterator}不是一个可迭代对象`)
}
this._datas = [];
for (const item of iterator) {
// console.log(item)
this.add(item)
}
}
add(data){
if(!this.has(data)){
this._datas.push(data);
}
return this;
}
has(data){
for (const item of this._datas) {
if(this.isEqual(data,item)){
return true
}
}
return false;
}
delete(data){
for(let i = 0 ;i < this._datas.length;i++){
const element = this._datas[i]
if(this.isEqual(data,element)){
this._datas.splice(i,1)
return true
}
}
return false
}
clear(){
this._datas.length = 0
}
get size(){
return this._datas.length
}
forEach(callback){
for (const item of this._datas) {
callback(item,item,this)
}
}
*[Symbol.iterator](){
for (const item of this._datas) {
yield item
}
}
isEqual(data1,data2){
if(data1 === 0 && data2 === 0){
return true
}
return Object.is(data1,data2)
}
}
2 map集合
2.1 创建
以键值对的形式存储,存储键名不重复的数据
```js
const map = new Map(iterable)
console.log(map)
````
2.2 方法
实例方法:
- size 集合长度 只读
- set(键名,键值) 添加数据
- get(键名) 获取数据
- has() 判断数据是否存在
- delete() 删除数据,返回值为是否删除成功
- clear() 清空集合
- for…of forEach
根据map自己仿写map集合
class MyMap{
constructor(iterator = []){
if(typeof iterator[Symbol.iterator] !== "function"){
throw new TypeError(`您所提供的${iterator}不是一个可迭代对象`)
}
this._datas = [];
for (const item of iterator) {
// item也是一个可迭代对象
if(typeof item[Symbol.iterator] !== "function"){
throw new TypeError(`您所提供的${item}不是一个可迭代对象`)
}
// this.set(item[0],item[1])
const iterator = item[Symbol.iterator]()//["a",1]
const key = iterator.next().value
const value = iterator.next().value
this.set(key,value)
}
}
set(key,value){
// console.log(key,value)
const obj = this._getObj(key)//undefined item
if(obj){
obj.value = value
}else{
this._datas.push({
key : key,
value : value
})
}
}
_getObj(key){
// 判断键名是否重复
for (const item of this._datas) {
if(this.isEqual(key,item.key)){
return item
}
}
}
isEqual(data1,data2){
if(data1 === 0 && data2 === 0){
return true
}
return Object.is(data1,data2)
}
get(key){
const obj = this._getObj(key)//undefined {"b":2}
if(obj){
return obj.value
}
return undefined
}
get size(){
return this._datas.length;
}
delete(key){
for(let i = 0;i<this._datas.length;i++){
const element = this._datas[i]
if(this.isEqual(key,element.key)){
this._datas.splice(i,1)
return true
}
}
return false
}
clear(){
this._datas.length = 0;
}
has(key){
return this._getObj(key) !== undefined;
}
forEach(callback){
for (const item of this._datas) {
callback(item.value,item.key,this)
}
}
*[Symbol.iterator](){
for (const item of this._datas) {
yield [item.key,item.value]
}
}
}
3 WeakSet集合和weakMap
WeakMap
因为 WeakMap 实例不会妨碍垃圾回收,所以非常适合保存关联元数据。来看下面这个例子,其中
使用了常规的 Map:
const m = new Map();
const loginButton = document.querySelector(’#login’);
// 给这个节点关联一些元数据
m.set(loginButton, {disabled: true});
假设在上面的代码执行后,页面被 JavaScript 改变了,原来的登录按钮从 DOM 树中被删掉了。但
由于映射中还保存着按钮的引用,所以对应的 DOM 节点仍然会逗留在内存中,除非明确将其从映射中
删除或者等到映射本身被销毁。
如果这里使用的是弱映射,如以下代码所示,那么当节点从 DOM 树中被删除后,垃圾回收程序就
可以立即释放其内存(假设没有其他地方引用这个对象):
const wm = new WeakMap();
const loginButton = document.querySelector(’#login’);
// 给这个节点关联一些元数据
wm.set(loginButton, {disabled: true});
WeakSet
相比于 WeakMap 实例,WeakSet 实例的用处没有那么大。不过,弱集合在给对象打标签时还是有
价值的。
来看下面的例子,这里使用了一个普通 Set:
const disabledElements = new Set();
const loginButton = document.querySelector(’#login’);
// 通过加入对应集合,给这个节点打上“禁用”标签
disabledElements.add(loginButton);
这样,通过查询元素在不在 disabledElements 中,就可以知道它是不是被禁用了。不过,假如
元素从 DOM 树中被删除了,它的引用却仍然保存在 Set 中,因此垃圾回收程序也不能回收它。
为了让垃圾回收程序回收元素的内存,可以在这里使用 WeakSet:
const disabledElements = new WeakSet();
const loginButton = document.querySelector(’#login’);
// 通过加入对应集合,给这个节点打上“禁用”标签
disabledElements.add(loginButton);
这样,只要 WeakSet 中任何元素从 DOM 树中被删除,垃圾回收程序就可以忽略其存在,而立即
释放其内存(假设没有其他地方引用这个对象)。