1. Set
- Set中存放的元素是不会重复,创建Set我们需要通过Set构造函数(暂时没有字面量创建的方式)
- Set中存放一个对象let a={name:'seikonn'};set.add(a)时,实际存放的是该对象的引用,及存放了a的地址,在堆内存中的{name:'seikonn'}被变量a和set同时指向,变量a发生变化a={},并不会影响set中的元素。
const set = new Set(1, 2, 3) //x const set = new Set([1, 2, 3]) //通过数组创建,或者使用add方法set.add(item) let obj1 = { name: "seikonn" } const set = new Set() set.add(obj1) console.log(set) obj1 = {name: '1'} console.log(set) //两次打印相同
1.1 属性
size:返回Set中元素的个数;
1.2 方法
add(value):添加某个元素,返回Set对象本身;
delete(value):从set中删除和这个值相等的元素,返回boolean类型;
has(value):判断set中是否存在某个元素,返回boolean类型;
clear():清空set中所有的元素,没有返回值;
forEach(callback, [, thisArg]):通过forEach遍历set;for of 也可遍历
1.3 数组去重
const arr = [10, 20, 10, 44, 78, 44]
const set = new Set(arr)
const newArray1 = [...set]
const newArray2 = Array.form(set)
2. WeakSet
- 和Set类似的另外一个数据结构称之为WeakSet,也是内部元素不能重复的数据结构。
2.1 weakSet和set的区别
- WeakSet中只能存放对象类型,不能存放基本数据类型;
- WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么GC可以对该对象进行回收;例:set中存放一个对象let a={name:'seikonn'};set.add(a)时,实际存放的是该对象的引用,及存放了a的地址,在堆内存中的{name:'seikonn'}被变量a和set同时指向,变量a发生变化a={},并不会影响set中的元素。如果使用weakSet,当a={}时,堆内存中的{name:'seikonn'}不被a指向了且weakSet中的元素对{name:'seikonn'}为弱引用,此时堆内存中的{name:'seikonn'}将被GC回收,weakSet中将也不会存放该对象;
- 没有size属性,clear()方法,forEach()方法,不能遍历,因为WeakSet只是对对象的弱引用,如果我们遍历获取到其中的元素,那么有可能造成对象不能正常的销毁;
- 存储到WeakSet中的对象是没办法获取的;
2.2 方法
add(value):添加某个元素,返回WeakSet对象本身;
delete(value):从WeakSet中删除和这个值相等的元素,返回boolean类型;
has(value):判断WeakSet中是否存在某个元素,返回boolean类型;
2.3 应用场景
const personSet = new WeakSet()
class Person {
constructor() {
personSet.add(this)
}
running() {
if (!personSet.has(this)) {
throw new Error("不能通过非构造方法创建出来的对象调用running方法")
}
console.log("running~", this)
}
}
let p = new Person()
p.running() // 正常调用
p = null // p对象清空,weakset里面也会自动移除(弱引用),被GC销毁
p.running.call({name: "why"}) // Error("不能通过非构造方法创建出来的对象调用running方法")
3. Map
-
用于存储映射关系
-
map.set(key, value)创建,或 new Map()传入一个ES8的Entries( [ [key,value], [key,value] ] )
-
map和set一样,为强引用,即key和value为对象时,并不会因为源对象发生改变而改变map和set里的元素
let obj1 = { name: "why" } let obj2 = { name: "seikonn" } const map = new Map() map.set(obj1, obj2) console.log(map) obj1 = {name: '1'} obj2 = {name: '2'} console.log(map) // 两次打印结果相同
3.1 与对象存储映射关系区别
- 事实上对象存储映射关系只能用字符串(ES6新增了Symbol)作为属性名(key);
- 某些情况下我们可能希望通过其他类型作为key,比如对象,这个时候会自动将对象转成字符串来作为key;
const obj1 = { name: "why" } const obj2 = { name: "kobe" } const info = { [obj1]: "aaa", //变量obj1作为key [obj2]: "bbb" //变量obj2作为key } console.log(info) // {[object Object]: "bbb"},只存在一个 const map1 = new Map() map1.set(obj1, "aaa") map1.set(obj2, "bbb") map1.set(1, "ccc") const map2 = new Map([ [obj1, 'aaa'], [obj2, 'bbb'], [1, 'ccc'] ]) console.log(map1) // {{name: 'why'} => 'aaa', {name: 'kobe'} => 'bbb', 1 => 'ccc'} console.log(map2) // {{name: 'why'} => 'aaa', {name: 'kobe'} => 'bbb', 1 => 'ccc'}
3.2 属性
size:返回Map中元素的个数;
3.3 方法
set(key, value):在Map中添加key、value,并且返回整个Map对象;
get(key):根据key获取Map中的value;
has(key):判断是否包括某一个key,返回Boolean类型;
delete(key):根据key删除一个键值对,返回Boolean类型;
clear():清空所有的元素;
forEach(callback, [, thisArg]):通过forEach遍历Map;for of 也可遍历
3.4 map遍历
map2.forEach((value, key) => {
console.log(value, key)
})
for (const item of map2) { // item为数组,第一项为key,第二项为value
console.log(item[0], item[1])
}
for (const [key, value] of map2) {
console.log(key, value)
}
4. WeakMap
和Map类型的另外一个数据结构称之为WeakMap,也是以键值对的形式存在的
4.1 WeakMap和Map的区别
- WeakMap的key中只能存放对象类型,不能存放基本数据类型;
- WeakMap的key对对象的引用是弱引用,如果没有其他引用引用这个对象,那么GC可以回收该对象;
- 没有size属性,clear()方法,forEach()方法,不能遍历
4.2 方法
set(key, value):在Map中添加key、value,并且返回整个Map对象;
get(key):根据key获取Map中的value;
has(key):判断是否包括某一个key,返回Boolean类型;
delete(key):根据key删除一个键值对,返回Boolean类型;
4.3 应用场景
- 响应式原理
const obj1 = { name: "why", age: 18 } function obj1NameFn1() { console.log("obj1NameFn1被执行") } function obj1NameFn2() { console.log("obj1NameFn2被执行") } function obj1AgeFn1() { console.log("obj1AgeFn1") } function obj1AgeFn2() { console.log("obj1AgeFn2") } const obj2 = { name: "kobe", height: 1.88, address: "广州市" } function obj2NameFn1() { console.log("obj1NameFn1被执行") } function obj2NameFn2() { console.log("obj1NameFn2被执行") } /* 当数据发生改变是指向指定函数 */ // 1.创建WeakMap const weakMap = new WeakMap() // 2.收集依赖结构 // 2.1.对obj1收集的数据结构 const obj1Map = new Map() obj1Map.set("name", [obj1NameFn1, obj1NameFn2]) obj1Map.set("age", [obj1AgeFn1, obj1AgeFn2]) weakMap.set(obj1, obj1Map) // 2.2.对obj2收集的数据结构 const obj2Map = new Map() obj2Map.set("name", [obj2NameFn1, obj2NameFn2]) weakMap.set(obj2, obj2Map) // 3.如果obj1.name发生了改变,用Proxy/Object.defineProperty监听 obj1.name = "james" // 执行一下 const targetMap = weakMap.get(obj1) const fns = targetMap.get("name") fns.forEach(item => item())