ES6
Set
-
在ES6之前,我们存储数据的结构主要有两种:数组、对象。
- 在ES6中新增了另外两种数据结构:Set、Map,以及它们的另外形式WeakSet、WeakMap。
-
Set是一个新增的数据结构,可以用来保存数据,类似于数组,但是和数组的区别是元素不能重复。
- 创建Set我们需要通过Set构造函数(暂时没有字面量创建的方式):
-
Set常见的属性和方法
- size 返回Set中元素的个数。[属性]
- add(value) 添加某个Set元素,并返回对象本身。
- delete(key):根据key删除一个键值对,返回Boolean类型。
- has(value) 判断某个元素是否存在,返回boolean类型。
- clear() 清空所有元素,没有返回值。
- forEach() 遍历
-
使用场景
-
数组去重
-
WeakSet
- 和Set类似的另外一个数据结构称之为WeakSet,也是内部元素不能重复的数据结构。
- 那么和Set有什么区别呢?
- 区别一:WeakSet中只能存放对象类型,不能存放基本数据类型;
- 区别二:WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么GC可以对该对象进行回收;
- 无法遍历
- 常见方法
- add(value):添加某个元素,返回WeakSet对象本身;
- delete(value):从WeakSet中删除和这个值相等的元素,返回boolean类型;
- has(value):判断WeakSet中是否存在某个元素,返回boolean类型;
- 使用场景
// Stack Overflow const pwset = new WeakSet(); class Person { // new的时候会执行constructor里面的代码 constructor() { pwset.add(this) } running() { if (!pwset.has(this)) { throw new Error('不能通过其他对象来调用running方法') } console.log("running", this) } } var p = new Person(); console.log(p.running()) // 会报错 p.running.call({ }) // 这里为什么使用WeakSet呢? // 因为WeakSet是弱引用 我们把p = null 后 就会被GC回收 // 如果使用Set 就会是强引用 ,我们把p = null 后 还要 set.delete(p) 才会被GC回收
强引用和弱引用的区别
- 弱引用 弱引用与强引用相对, 一个对象若只被弱引用所引用,则被认为是不可访问(或弱可访问)的,并因此可能在任何时刻被回收。因此使用弱引用可以防止内存泄漏。在JavaScript中弱引用的
WeakMap
和WeakSet
。
强引用 JavaScript中最常见的就是声明一个变量并且将一个引用类型数据(对象)
赋值给这个变量,这种情况就是强引用。只要该对象还被引用,垃圾回收机制GC
就不会回收该对象或者属性。对于一个普通对象,将全部引用该对象的变量关系相应设置为null
,便能等待垃圾回收机制GC
回收
map
-
数据结构Map,用于存储映射关系。
- 事实上我们对象存储映射关系只能用字符串(ES6新增了Symbol)作为属性名(key);
- 某些情况下我们可能希望通过其他类型作为key,比如对象,这个时候会自动将对象转成字符串来作为key;对象的key内部会自动toString();
-
Map常见的属性和方法
- size 返回Set中元素的个数。[属性]
- set(key, value):在Map中添加key、value,并且返回整个Map对象。
- get(key):根据key获取Map中的value。
- has(value) 判断某个元素是否存在,返回boolean类型。
- clear() 清空所有元素,没有返回值。
- forEach(value,key,map) 遍历
-
使用场景
- 缓存
-
const decorator = (fn) => { const mapList = new Map(); return (x, y) => { const sum = `${x}${y}`; if (mapList.has(sum)) { return mapList.get(sum); } const res = fn(x, y) mapList.set(sum, res); return res; } } let work = (a, b) => { return a + b; } work = decorator(work) work(1, 2); work(1, 2); // 这里实际上用的缓存 work(3, 4); work(3, 4); // 这里实际上用的缓存
WeakMap
-
WeakMap的key只能使用对象,不接受其他的类型作为key
-
WeakMap的key对对象想的引用是弱引用,如果没有其他引用引用这个对象,那么GC可以回收该对象;
-
WeakMap常见方法:
- set(key, value):在Map中添加key、value,并且返回整个Map对象
- get(key):根据key获取Map中的value
- has(key):判断是否包括某一个key,返回Boolean类型
- delete(key):根据key删除一个键值对,返回Boolean类型
-
Weak使用场景(vue3响应式原理)
-
const obj1 = { name: "why", age: 18 } const obj2 = { name: "why", age: 18 } // 1.创建WeakMap const weakMap = new WeakMap(); // 2. 收集依赖结构 // 2.1 使用map来收集 const obj1Map = new Map(); obj1Map.set("name", [obj1GetName, obj1SetName]) obj1Map.set("age", [obj1GetAge, obj1SetAge]) weakMap.set(obj1, obj1Map) // 3.如果obj1.name发生改变 // Proxy/Object.defineProperty obj1.name = "test"; const targetMap = weakMap.get(obj1); const fns = targetMap.get("name") fns.forEach(item => item()) function obj1GetName() { console.log("obj1GetName") } function obj1SetName() { console.log("obj1SetName") } function obj1GetAge() { console.log("obj1GetAge") } function obj1SetAge() { console.log("obj1SetAge") }