- 在ES6之前,我們存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu)主要有兩種:數(shù)組、對(duì)象。
- 在ES6中新增了另外兩種數(shù)據(jù)結(jié)構(gòu):Set、Map,以及它們的另外形式WeakSet、WeakMap。
Set和WeakSet
Set的使用
- Set是一個(gè)新增的數(shù)據(jù)結(jié)構(gòu),可以用來(lái)保存數(shù)據(jù),類(lèi)似于數(shù)組,但是和數(shù)組的區(qū)別是元素不能重復(fù)。
- 創(chuàng)建Set我們需要通過(guò)Set構(gòu)造函數(shù)(暫時(shí)沒(méi)有字面量創(chuàng)建的方式):
- 可以發(fā)現(xiàn)Set中存放的元素是不會(huì)重復(fù)的,那么Set有一個(gè)非常常用的功能就是給數(shù)組去重。
//通過(guò)new關(guān)鍵字創(chuàng)建
const set1 = new Set();
set1.add(1)
set1.add(2)
set1.add(2)
set1.add({name:13})
console.log(set1); //Set(3) { 1, 2, { name: 13 } }
//根據(jù)數(shù)組創(chuàng)建set對(duì)象
const set2 = new Set([1,2,3,4,5,5])
console.log(set2); //Set(5) { 1, 2, 3, 4, 5 }
//將set轉(zhuǎn)變?yōu)閿?shù)組
const newArray1 = [...set2]
console.log(newArray1);
const newArray2 = Array.from(set2)
console.log(newArray2);
Set的常見(jiàn)屬性和方法
- size:返回Set中元素的個(gè)數(shù);
method:
- add(value):添加某個(gè)元素,返回Set對(duì)象本身;
- delete(value):從set中刪除和這個(gè)值相等的元素,返回boolean類(lèi)型;
- has(value):判斷set中是否存在某個(gè)元素,返回boolean類(lèi)型;
- clear():清空set中所有的元素,沒(méi)有返回值;
- forEach(callback, [, thisArg]):通過(guò)forEach遍歷set;
- Set是支持for of的遍歷的。
WeakSet的使用
- 和Set類(lèi)似的另外一個(gè)數(shù)據(jù)結(jié)構(gòu)稱(chēng)之為WeakSet,也是內(nèi)部元素不能重復(fù)的數(shù)據(jù)結(jié)構(gòu)。
- 和Set的區(qū)別
區(qū)別一:WeakSet中只能存放對(duì)象類(lèi)型,不能存放基本數(shù)據(jù)類(lèi)型;
區(qū)別二:WeakSet對(duì)元素的引用是弱引用,如果沒(méi)有其他引用對(duì)某個(gè)對(duì)象進(jìn)行引用,那么GC可以對(duì)該對(duì)象進(jìn)行回收(弱引用可以理解為有地址指向?qū)ο?,但是?duì)象依然能夠被銷(xiāo)毀);
const wset = new WeakSet()
const obj1 = {
name:"zs",
age:14
}
const obj12 = {
name:"zsss",
age:142
}
wset.add(10) //報(bào)錯(cuò):invalid val used
wset.add(obj1)
wset.add(obj12)
console.log(wset);
WeakSet常見(jiàn)的方法:
- add(value):添加某個(gè)元素,返回WeakSet對(duì)象本身;
- delete(value):從WeakSet中刪除和這個(gè)值相等的元素,返回boolean類(lèi)型;
- has(value):判斷WeakSet中是否存在某個(gè)元素,返回boolean類(lèi)型;
const wset = new WeakSet();
const obj1 = {
name: "zs",
age: 14,
};
const obj2 = {
name: "zsss",
age: 142,
};
const obj3 = {
name: "zsss",
age: 142,
};
// wset.add(10)
wset.add(obj1);
wset.add(obj2);
console.log(wset.has(obj2)); //true
console.log(wset.has(obj3)); //false,注意
wset.delete(obj2);
console.log(wset.has(obj2)); //false
WeakSet的應(yīng)用
- 阻止其他的對(duì)象的借用調(diào)用
const wset = new WeakSet();
class Person {
constructor() {
wset.add(this); //將創(chuàng)建的對(duì)象保存到weakset中
}
running() {
//每次調(diào)用該方法先判斷weakset中是否有保證該對(duì)象,保證只有Person類(lèi)的子對(duì)象可以調(diào)用
if (!wset.has(this)) {
throw new Error("不能通過(guò)其他類(lèi)型的對(duì)象調(diào)用running方法");
}
console.log("running", this);
}
}
Map和WeakMap
Map的使用
- Map用于存儲(chǔ)映射關(guān)系。
之前我們可以使用對(duì)象來(lái)存儲(chǔ)映射關(guān)系,有什么區(qū)別呢?
對(duì)象存儲(chǔ)映射關(guān)系只能用字符串(ES6新增了Symbol)作為屬性名(key);某些情況下我們可能希望通過(guò)其他類(lèi)型作為key,比如對(duì)象,這個(gè)時(shí)候會(huì)自動(dòng)將對(duì)象轉(zhuǎn)成字符串來(lái)作為key;那么我們就可以使用Map:
const obj = { name: "zs", age: 18, height: 1.88 };
const obj2 = { name: "zsss", age: 11, height: 1.55 };
const map1 = new Map();
map1.set(obj, "abc");
map1.set(obj2, "bcd");
console.log(map1);
/* Map(2) {
{ name: 'zs', age: 18, height: 1.88 } => 'abc',
{ name: 'zsss', age: 11, height: 1.55 } => 'bcd'
} */
console.log(map1.get(obj)); //abc
Map的常用屬性方法
- size:返回Map中元素的個(gè)數(shù);
Map常見(jiàn)的方法:
- set(key, value):在Map中添加key、value,并且返回整個(gè)Map對(duì)象;
- get(key):根據(jù)key獲取Map中的value;
- has(key):判斷是否包括某一個(gè)key,返回Boolean類(lèi)型;
- delete(key):根據(jù)key刪除一個(gè)鍵值對(duì),返回Boolean類(lèi)型;
- clear():清空所有的元素;
- forEach(callback, [, thisArg]):通過(guò)forEach遍歷Map;
- Map也可以通過(guò)for of進(jìn)行遍歷。
WeakMap的使用
- 和Map區(qū)別
區(qū)別一:WeakMap的key只能使用對(duì)象,不接受其他的類(lèi)型作為key;
區(qū)別二:WeakMap的key對(duì)對(duì)象想的引用是弱引用,如果沒(méi)有其他引用引用這個(gè)對(duì)象,那么GC可以回收該對(duì)象;
WeakMap的常用屬性方法:
- set(key, value):在Map中添加key、value,并且返回整個(gè)Map對(duì)象;
- get(key):根據(jù)key獲取Map中的value;
- has(key):判斷是否包括某一個(gè)key,返回Boolean類(lèi)型;
- delete(key):根據(jù)key刪除一個(gè)鍵值對(duì),返回Boolean類(lèi)型;
WeakMap的應(yīng)用 :
- vue3響應(yīng)式原理
//WeakMap(fkey(對(duì)象):value.}):key是一個(gè)對(duì)象,弱引用
const targetMap = new WeakMap();
function getDep(target, key) {
//·1.根據(jù)對(duì)象(target)取出對(duì)應(yīng)的Map對(duì)象
let depsMap = targetMap.get(target);
if (!depsMap) {
depsMap = new Map();
targetMap.set(target, depsMap);
//·2.取出具體的dep對(duì)象
let dep = depsMap.get(key);
if (!dep) dep = new Dep();
depsMap.set(key, dep);
}
return dep;
}