Set和Map

时间:2021-09-16 11:27:10   收藏:0   阅读:28

一、Set集合

let arr = [1, 3,4, 2, 2, 1, 1]
let set=new Set(arr)// Set(4) {1, 3, 4, 2}

1.1.基本操作

let s1 = new Set([1,2,3]);
for(let item of s1){
      console.log(item);//1 2 3
}
for (let item of s1.keys()){
    console.log(item);//1 2 3
}
for (let item of s1.values()){
    console.log(item);//1 2 3
}
for (let item of s1.entries()){
    console.log(item);//[1, 1] [2, 2] [3, 3]
}
s1.forEach((item,index) => console.log(item))//1 2 3
let s1 = new Set([1,2,3]);

//1、构造函数是Set()
console.log(s1.constructor);//? Set() { [native code] }
//2、求元素的个数
console.log(s1.size);//3
//3、添加元素
s1.add(‘22‘).add(22);//Set(5) {1, 2, 3, ‘22‘, 22}
//4、删除元素
s1.delete(2);//true==>s1 Set(3) {1, 3, ‘22‘, 22}
//5、检测set集合中是否存在某个值,存在返回true,不存在返回false
s1.has(‘22‘)//true
//6、清空元素
s1.clear();//==>s1 Set(0) {}

注:

1.2.应用

应用1:数组去重

let arr = [1, 3,4, 2, 2, 1, 1]
//new Set(arr)不是一个数组,可以通过扩展运算符变成数组
let result = [...new Set(arr)];
console.log(result);//[1, 3, 4, 2]
//可以通过Array.from变成数组
let result1 = Array.from(new Set(arr));
console.log(result1);//[1, 3, 4, 2]

应用2:并集

let arr1 = [1, 2]
let arr2 = [2,4,5]
let result = [...new Set([...arr1,...arr2])];
console.log(result); [1, 2, 4, 5]

应用3:交集

let arr1 = [1, 2, 4]
let arr2 = [2,4,5]
let result = arr1.filter(item =>new Set(arr2).has(item)); 
console.log(result); //[2, 4]

应用4:差集

let arr1 = [1, 2, 4]
let arr2 = [2,4,5]
let result = arr1.filter(item =>!new Set(arr2).has(item)); 
console.log(result); //[1]

二、WeakSet

2.1.与Set 的区别

const ws = new WeakSet();//WeakSet {}
ws.add(1);//报错,1不是对象

垃圾回收机制

内存泄漏

2.1.基本操作

let ws = new WeakSet([{}]);
const obj = {};
const foo = {};
//1、构造函数是WeakSet()
console.log(ws.constructor);//? WeakSet() { [native code] }
//2、添加元素
ws.add(obj).add(foo);//WeakSet {{…}, {…}, {…}}
//3、删除元素
ws.delete(obj);//true==>ws WeakSet {{…}, {…}}
//4、检测WeakSet集合中是否存在某个对象,存在返回true,不存在返回false
ws.has(foo)//true

/**************************区别******************************/
//1、无法遍历操作
ws.forEach // undefined
//2、求元素的个数,没有size属性
console.log(ws.size);//undefined
//3、清空元素,已废弃使用
ws.clear();//报错

三、Map字典

Map对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。

[key, value] 的形式储存

3.1.与 Objects 的区别

3.2.基本操作

const m = new Map([       
    [‘name‘, ‘hjj‘],
    [‘age‘, ‘18‘]
]);
for(let item of m){
      console.log(item);//[‘name‘, ‘hjj‘] [‘age‘, ‘18‘]
}
for (let item of m.keys()){
    console.log(item);//name age
}
for (let item of m.values()){
    console.log(item);//hjj 18
}
for (let item of m.entries()){
    console.log(item);//[‘name‘, ‘hjj‘] [‘age‘, ‘18‘]
}
m.forEach((item,index) => console.log(item,index))//hjj name  18 age
const m = new Map([[‘day‘,1]])
//1、构造函数是Map()
console.log( m.constructor);//? Map() { [native code] }
//2、求元素的个数
console.log(m.size);//1
//3、添加新元素
m.set(‘name‘,‘hjj‘);//Map(2) {‘day‘ => 1, ‘name‘ => ‘hjj‘}
//4、查找特定的Key。有返回所对应的值,否则返回undefined。
m.get(‘name‘);//‘hjj‘
//5、检测Map对象中是否有Key所对应的值,有返回true,否则返回false。
m.has(‘name‘);//true
// 6、删除元素
m.delete(‘name‘);//true==>m Map(1) {‘day‘ => 1}
//7、清空元素
m.clear(); //==>m Map(0) {}

3.3.应用

Map与数组转换

const arr =[[‘name‘, ‘hjj‘],[‘‘, ‘18‘]];
//数组==>Map
let m=new Map(arr) //m Map(2) {‘name‘ => ‘hjj‘, ‘age‘ => ‘18‘}
//Map==>数组
//1、扩展运算符
let result = [...new Map(arr)];
console.log(result);//[[‘name‘, ‘hjj‘],[‘age‘, ‘18‘]]
//2、Array.from
let result1 = Array.from(new Map(arr));
console.log(result1);//[[‘name‘, ‘hjj‘],[‘age‘, ‘18‘]]

Map转为对象

function mapToObj(map){
    let obj = Object.create(null);
    for(let [key,value] of map){
        obj[key] = value;
    }
    return obj;
}
const m = new Map();
m.set(‘name‘,‘hjj‘).set(‘age‘,18);
let result=mapToObj(m);//{name: ‘hjj‘, age: 18}

对象转为Map

function objToMap(obj){
    let map = new Map();
    for (let k of Object.keys(obj)){
        map.set(k,obj[k]);
    }
    return map;
}
const obj={name: ‘hjj‘, age: 18};
let result=objToMap(obj)//Map(2) {‘name‘ => ‘hjj‘, ‘age‘ => 18}

克隆

var m1 = new Map([[‘name‘, ‘hjj‘],[‘age‘, ‘18‘]]);
var m2= new Map(m1)//m2=>Map(2) {‘name‘ => ‘hjj‘, ‘age‘ => ‘18‘}
m1===m2//false==>Map对象构造函数生成实例,迭代出新的对象。

Map 的合并

var m1 = new Map([[‘name‘, ‘hjj‘],[‘day‘, ‘1‘]]);
var m2= new Map([[‘age‘, ‘18‘],[‘name‘, ‘hhh‘]]);
var m= new Map([...m1,...m2])//Map(3) {‘name‘ => ‘hhh‘, ‘day‘ => ‘1‘, ‘age‘ => ‘18‘}

四、WeakMap

4.1.与Map的区别

const wm = new WeakMap();//WeakMap {}
wm.set(‘name‘, ‘hhh‘)//报错,name键名不是对象

应用:

const wm = new WeakMap();
const element = document.getElementById(‘example‘);
wm.set(element, ‘some information‘);
wm.get(element) // "some information"
//一旦消除对该节点的引用,它占用的内存就会被垃圾回收机制释放。Weakmap 保存的这个键值对,也会自动消失。

4.2.基本操作

let wm = new WeakMap();
const obj = {};
const foo = {};
//1、构造函数是WeakMap()
console.log(wm.constructor);//? WeakMap() { [native code] }
//2、添加元素
wm.set(obj,1).set(foo,2);//WeakMap {{…} => 1, {…} => 2}
//3、查找特定的Key。有返回所对应的值,否则返回undefined。
wm.get(obj);//1
// 4、删除元素
wm.delete(obj);//true==>wm WeakMap {{…} => 2}

/**************************区别******************************/
//1、无法遍历操作
wm.forEach // undefined
//2、求元素的个数,没有size属性
console.log(wm.size);//undefined
//3、清空元素,已废弃使用
wm.clear();//报错

4.3.应用

典型场合就是 DOM 节点作为键名

let myElement = document.getElementById(‘logo‘);
let myWeakmap = new WeakMap();
myWeakmap.set(myElement, {timesClicked: 0});

myElement.addEventListener(‘click‘, function() {
  let logoData = myWeakmap.get(myElement);
  logoData.timesClicked++;
}, false);
/*
 + myElement是一个 DOM 节点,每当发生click事件,就更新一下状态.
 + 将这个状态作为键值放在 WeakMap 里,对应的键名就是myElement。
 + 一旦这个 DOM 节点删除,该状态就会自动消失,不存在内存泄漏风险。
*/

部署私有属性

const _counter = new WeakMap();
const _action = new WeakMap();

class Countdown {
  constructor(counter, action) {
    _counter.set(this, counter);
    _action.set(this, action);
  }
  dec() {
    let counter = _counter.get(this);
    if (counter < 1) return;
    counter--;
    _counter.set(this, counter);
    if (counter === 0) {
      _action.get(this)();
    }
  }
}

const c = new Countdown(2, () => console.log(‘DONE‘));

c.dec()
c.dec()// DONE
/*
+ Countdown类的两个内部属性_counter和_action,是实例的弱引用。
+ 所以如果删除实例,它们也就随之消失,不会造成内存泄漏。
*/

五、总结

Set WeakSet Map WeakMap
成员 任何类型 对象 键值对 键名为对象的键值对
成员特点 唯一、无序且不重复 成员都是弱引用,可以被垃圾回收机制回收 键、值可为任何类型 键名是弱引用,键名所指向的对象可以被垃圾回收
遍历 可遍历 不可遍历 可遍历 不可遍历
属性 constructor、size constructor constructor、size constructor
方法 add、delete、has、clear add、delete、has set、get、delete、has、clear set、get、delete、has
场景 数组去重等数组操作 节点保存 各种数据格式转换 节点作为键名、部署私有属性

参考转自:
ES6之Set和Map数据结构深入学习

原文:https://www.cnblogs.com/jiajia-hjj/p/15270129.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!