詳解es6中set,map,WeakSet,Weakmap的區別和用法

set,map,WeakSet,Weakmap 在js的使用頻率越來越高,特備是一些新框架的源碼中,本篇博文將其基本用法和區別做一總結,加強記憶。

set

set定義及特徵

  • 在js中Set 對象允許存儲任何類型的唯一值,無論是原始值或者是對象引用。
  • 頂層數據結構不具備key—>value特徵,內部會自動加index序列。
  • 可以存儲不同類型的任何數據。

如何理解唯一性:對於原始數據類型(boolean,number,string,null,undefined)如果存儲相同值則只會保存一個,對於引用類型做“==”判斷即引用地址完全相同則只會存一個。

   let set = new Set();  
//a,b屬於object 值完全相同
    let a = {
        name:"cc",
        age:28
    };
    let b = {
        name:"cc",
        age:28
    };
   
//c,d屬於number類型 值完全相同
    let c = 0,d = 0;
//e,f 屬於Date類型,值相同
    let e=f = new Date();

    set.add(a);
    set.add(b);
    set.add(c);
    set.add(d);
    set.add(e);
    set.add(f);

    a= "abc";
    b = {
        name:"cc",
        age:30
    }
    set.add(a);
    set.add(b);

    console.log(set);

在這裏插入圖片描述
set方法

  • size屬性: 返回集合的元素個數。(類似數組的長度length)
  • add(value)方法: 向集合中添加一個元素value。注意:如果向集合中添加一個已經存在的元素,不報錯但是集合不會改變。
  • delete(value)方法: 從集合中刪除元素value。
  • has(value)方法: 判斷value是否在集合中,返回true或false.
  • clear()方法: 清空集合。

set應用場景

鑑於set存儲值的不重複特性,經常被用來求數組去重,交集,並集,差集等操作。

  1. 數組去重
let arry = [1, 2, 3, 4, 4,1,2,3,2];
var mySet = new Set(arry);
 let newArry = [...mySet]; // [1, 2, 3, 4]
  1. 求並集,交集,差集。
    //set求並集
    let arryA= [2,3,4,5,6],arryB = [3,4,5,6,7,8];
    let setAB = new Set([...arryA,...arryB]);
    let newArryAB = [...setAB];
    console.log(newArryAB); //[2,3,4,5,6,7,8]

    //求交集
    let arryC= [2,3,4,5,6],arryD = [3,4,5,6,7,8];
    let setC = new Set(arryC);
    let setD = new Set(arryD);
    let newArryC_D = arryA.filter(x=>setD.has(x));
    console.log(newArryC_D); //[3,4,5,6]

    //求差集
    let newArryD_C = arryA.filter(x=>!setD.has(x));
    let newArryD_D = arryB.filter(x=>!setC.has(x));
    let newArryCD = [...newArryD_C,...newArryD_D];
    console.log(newArryCD); //[2,7,8]

map

map定義及特徵

Map 對象保存鍵值對。任何值(對象或者原始值) 都可以作爲一個鍵或一個值。

Map常用屬性及增刪改查方法:

  • size: 屬性,取出字典的長度
  • set(key, value):方法,向字典中添加新元素
  • get(key):方法,通過鍵查找特定的數值並返回
  • has(key):方法,判斷字典中是否存在鍵key
  • delete(key):方法,通過鍵 key 從字典中移除對應的數據
  • clear():方法,將這個字典中的所有元素刪除

與Object的區別:

  • 一個 Object 的鍵只能是字符串或者 Symbols,但一個 Map 的鍵可以是任意值。
  • Map 中的鍵值是有序的(FIFO 原則),而添加到對象中的鍵則不是。
  • Map 的鍵值對個數可以從 size 屬性獲取,而 Object 的鍵值對個數只能手動計算。
  • Object 都有自己的原型,原型鏈上的鍵名有可能和你自己在對象上的設置的鍵名產生衝突,而map健不可重複,如果鍵名衝突則會覆蓋對應的值。
let map = new Map();
    let s = {
        name:'cc',
        job:'programmer'
    }
    let m ={
        dd:'cdcdcd',
        do:function(str){
            console.log(str)
        }
    }
    map.set(s,m);
    map.set(m,s);
    map.set(0,s);
    map.set(0,m);
    console.log(map)

在這裏插入圖片描述
map的遍歷

for … of
forEach

 for(let [key,value] of map){
        console.log("key:"+JSON.stringify(key)+"-------value:"+JSON.stringify(value))
    }

  map.forEach((value,key)=>{
      console.log("key:"+JSON.stringify(key)+"-------value:"+JSON.stringify(value))
  })

map與數組之間的轉換

 let arryK = [[1,2],[3,4],[5,6]];

    let mapK = new Map(arryK);

    let mapP = Array.from(mapK);

    console.log(mapK);
    console.log(mapP);

在這裏插入圖片描述
map的複製

let mapV= new Map(map);

WeakSet

和Set結構類似,也是不重複的值的集合,但WeakSet的成員只能是對象。

WeakSet的API:add() //增 ;delete() //刪; has() //是否存在

注意:ws沒有size屬性,不可遍歷。因爲WeakSet的成員都是弱引用,隨時可能消失,成員是不穩定的。

WeakSet的用處
(1)使用ws儲存DOM節點,就不用擔心節點從文檔移除時,會引發內存泄漏(即在被移除的節點上綁定的click等事件)。
(2)下面代碼保證了Foo的實例方法,只能在Foo的實例上調用。這裏使用 WeakSet 的好處是,foos對實例的引用,不會被計入內存回收機制,所以刪除實例的時候,不用考慮foos,也不會出現內存泄漏。

WeakSet

WeakMap與Map的區別:
WeakMap 對象是一組鍵值對的集合,其中的鍵是弱引用對象,而值可以是任意。

注意,WeakMap 弱引用的只是鍵名,而不是鍵值。鍵值依然是正常引用。

WeakMap 中,每個鍵對自己所引用對象的引用都是弱引用,在沒有其他引用和該鍵引用同一對象,這個對象將會被垃圾回收(相應的key則變成無效的),所以,WeakMap 的 key 是不可枚舉的。

用WeakMap來實現私有屬性

    //weakmap

    let Person = (function() {

        let privateData = new WeakMap();

        function Person(name,age) {
            privateData.set(this,  {name:name,age:age});
        }

        Person.prototype.getName = function() {
            return privateData.get(this).name;
        };
        Person.prototype.getAge = function() {
            return privateData.get(this).age;
        };
        Person.prototype.setName = function(name) {
            let obj = privateData.get(this)
            obj.name = name;
        };
        Person.prototype.setAge = function(age) {
            let obj = privateData.get(this)
            obj.age = age;
        };

        return Person;
    }());

 let ssf = new Person("zhang",19);
    console.log(ssf.getName());
    console.log(ssf.getAge());
    ssf.setName("liu");
    ssf.setAge(90)
    console.log(ssf.getName());
    console.log(ssf.getAge());

在這裏插入圖片描述

發佈了77 篇原創文章 · 獲贊 8 · 訪問量 6859
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章