深入浅出JS—13 Set和Map应用场景

ES6之前JS中只有两种数据结构:数组Array,对象Object
ES6中新增了两种数据结构Set Map,以及另外形式 WeakMap WeakSet

1. 集合Set

集合和数组的区别

  • 数组:元素可以重复
  • 集合:元素不可重复

构造集合
需要调用Set构造函数,无字面量方式,参数可以传入一个可迭代对象

const set1 = new Set();
set1.add("item1");

const set2 = new Set([1, 2, 3, 3]);
consoel.log(set2); // [1, 2, 3]

Set属性

set.size; // 返回set的大小

Set方法
add delete has clear forEach for-of
在这里插入图片描述

// 五种方法测试
const set = new Set(["item1", "item2", 1, 2]);
// add
set.add("3");
// delete
set.delete("3");
// has
set.has("3"); // false
// clear
set.clear();

// 遍历
set.forEach(item => console.log(item));
for( const item of set){
  console.log(item);
}

2. WeakSet

WeakSet和Set的区别如下

  • WeakSet只能存放对象类型
  • 对于对象是弱引用,GC自动回收时不会将弱引用算在内,所以会自动回收

弱引用示意

let obj = { name: 'xs' };
const weakset = new WeakSet();
weakset.add(obj);

obj = null;
// 取消对{ name: 'xs' }的强引用
// 一段时间后GC会将weakmap中的obj对象回收

WeakSet的方法

  • has delete add
  • 无clear forEach for-of 所以存入WeakSet的东西无法获取,所以基本上没啥用
  • 无size方法

WeakSet的应用:记录是否出现过

const weakset = new WeakSet();
class Person{
 constructor(name){
 	weakset .add(this)
	this.name = name
 }
 running() {
 	if(!weakset .has(this)) throw new Error("不能通过非构造方法创建出来的对象调用running方法");
 	console.log(`${this.name} is running`)
 }
}

const p = new Person('xs');

p.running.call({name: 'kobe'});// 报错:不能通过非构造方法创建出来的对象调用running方法
p.running() // 可以调用

3. 映射Map

Map和对象的区别

  • 对象中的key只能为字符串或者Symbol类型,Map没有限制,key可以为对象
  • 对象不可以for-of/forEach遍历(可以用for-in遍历),但是Map可以

对象的声明

const map= new Map();

const obj1 = {name:'xs'};
map.set(obj1,'aaa');
console.log(map); // { { name: 'xs' } => 'aaa' } 为了区分对象,返回值用箭头表示映射

对象的属性

map.size 

对象的方法
get set has delete clear forEach for-of

在这里插入图片描述

// 遍历
for(const item of map){
  console.log(item);// 返回的是一个数组[key1, value1]
}

for(const [key, value] of map){
  console.log(key, value);
}

4.WeakMap

WeakMap和Map的区别

  • WeakMap中key只能是对象
  • WeakMap对于key是弱引用

WeakMap的方法

  • get set has delete
  • 无clear方法 遍历方法
  • 无size属性

WeakMap的应用:多层记录本
场景: Vue3响应式原理中收集的依赖以WeakMap形式组织起来

const obj1 = {
  name: "xs",
  age: 18,
};

const obj2 = {
  name: "kobe",
  age: 28,
};

function change1Name1() {
  console.log("object1 change name1");
}

function change1Name2() {
  console.log("object1 change name2");
}

function change1Age1() {
  console.log("object1 change age1");
}

function change1Age2() {
  console.log("object1 change age2");
}

function change2Name1() {
  console.log("object2 change name1");
}

function change2Name2() {
  console.log("object2 change name2");
}

// 1 创建weakMap
const weakmap = new WeakMap();

// 2.收集依赖结构
// 2.1对obj1收集响应函数
const mapObj1 = new Map();
mapObj1.set("name", [change1Name1, change1Name2]);
mapObj1.set("age", [change1Age1, change1Age2]);
weakmap.set(obj1, mapObj1);

// 2.2对obj2收集响应函数
const mapObj2 = new Map();
mapObj2.set("name", [change2Name1, change2Name2]);
weakmap.set(obj2, mapObj2);

// 3 监听改变,有很多实现形式,还可以用Proxy
let _name = obj1.name;
Object.defineProperty(obj1, "name", {
  configurable: true,
  enumerable: true,
  get: function () {
    return _name;
  },
  set: function (value) {
    _name = value;
    weakmap
      .get(obj1)
      .get("name")
      .forEach((fn) => fn());
  },
});

obj1.name = 12; // 函数change1Name1和change1Name2就会执行
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值