ECMAscript6 中Set數據結構

大家好混元霹靂手Ziksang又來了,給大家講講es6,Set這個新的數據結構

大年初三,先給大家拜個年,我知道我的拜方式錯了?。〖t包即將打到你的支付寶中,請接收!

2017年的目標就是把ecmscript6所有的知識點全弄明白,我相信以后會基于ecmascript6的新特性肯定會出一些更牛B的框架,就像vue一樣用了Object.defineProperty ecmascript5的新特性來進行數據劫持,所以我很期待

簡單介紹一下吧

Set基本介紹

Set是ES6中數據結構中其中一個新的特性,我們看上去往往很像數組,但是他的每個成員都是唯一的,不會存在重復的值

Set也是一個構造函數,用來生成Set這個數據結構,我們可以看看他實例原型上有那些東西,簡單看一下

在set原型上放了這么多方法,接下來我一一介紹一下吧,記住學習一定要學到根本?。。?!

注意我的每一步代碼都是自上而下有著關聯的

add方法

let set = new Set()
let array = [1,"ziksang",3,3,true,5,5]
array.forEach(item => {
        set.add(item)
})
console.log(set)
// Set {1, "ziksang", 3, true, 5}

1.先new出set這個構造函數實列,我們存在set變量上
2再聲明一個array這個數組,里面的數組成員有各種數據類型和重復的值
3.用Set原型上add方法把用es5中each方法把每個值添加到set成員里
4.打印出來是一個對象,里面相同類型相同值都會去掉,但是里面的整體結構和類組數對象一樣,有著自己的長度

 for (let i of set) {
         console.log(i);
         console.log(typeof i)
}

以上我們再次用for of的方法也,同樣也是es6的新特性,此時就可以把set對象里每一個值可以打印出來,里面的打印出的每一個數據類型也同樣是我們array數組里定義的數據類型


上面代碼通過add方法向Set結構加入成員,結果表明Set結構不會添加重復的值。
Set函數可以接受一個數組(或類似數組的對象)作為參數,用來初始化。

        function demo(){
            let set = new Set(arguments)
            console.log(set)
        }
        demo(1,2,4,4,5)
        //Set {1, 2, 4, 5}
        let set = new Set([1,2,4,4,5])
        console.log(set)
        //Set {1, 2, 4, 5}

1.Set函數里我們可以接受參數來作為初始化跟new Array[1,2,3,4]性質是一樣的
2.第一個我在demo函數里讓set函數接收了demo里arguments對象作為參數
3.第二個我直接在set函數里放入一個數組
4.兩都console.log()打印出來的是一樣的,同樣不會包含同類型同樣的值的成員

size方法

size方法是用來判斷出,set里成員的個數

var items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
items.size // 5

1.雖然上面我定義了8個成員數量,但是最后個數只有5個,因為還是同樣的不會把重復同類型同樣的值算進去,只算一個

數組去重方法
在以前數我面試的時候別人一直接我數組去重怎么樣,我現在只想回答他,看下面

       let array = [1,2,2,3,3,4]
       let set = new Set(array)
       array = [...set]
       console.log(array)
      //[1,2,3,4]

1.聲明一個數組
2.把數組作為set構造函數的初始化成員
3.再把set用[...set]來重新復制給array//簡稱拓展運算符...
4.擴展運算符(...)內部使用for...of循環,所以也可以用于Set結構。

關于類型轉換,NaN,object的區別

在往set數據結構中添加值的值,并不會發生類型轉換,4和“4”不同的數據類型不會發生轉換,他的內部是用Same-value equality,也就是跟恒等差不多,但是NaN不一樣很特殊

       console.log(NaN === NaN) //false
       const a = NaN;
       const b = NaN;
       const c = "1";
       const d = 1;
       let set = new Set()
       set.add(a)
       set.add(b)
       set.add(c)
       set.add(d)
       console.log(set) //Set {NaN, "1", 1}

1.如果單純的比對NaN === NaN肯定是不相等的,但是在set數據結構中,里面的計算原理是把NaN看成相等的


對于兩個對象來說,無是里面是否有值 ,可者有什么樣的值都是不相等的,空對象也不相等

       let set = new Set()
       set.add({})
       set.add({})
       console.log(set)  //Set {Object {}, Object {}}
       console.log(set.size)//2

1.可以看出空對象是不相等的,所以它們被視為兩個值。總個數依然是2個


Set實例的屬性和方法,也就是Set構造函數上定義的方法和屬性

Set結構的實例有以下屬性。
Set.prototype.constructor:構造函數,默認就是Set函數。
Set.prototype.size:返回Set實例的成員總數。

Set實例的方法分為兩大類:操作方法(用于操作數據)和遍歷方法(用于遍歷成員)。下面先介紹四個操作方法。

add(value):添加某個值,返回Set結構本身。
delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功。
has(value):返回一個布爾值,表示該值是否為Set的成員。
clear():清除所有成員,沒有返回值。

size和add我在前面已經講過了,再少許提一下吧

        let set = new Set()
        set.add(3).add(2).add(2).add("ziksang");
        console.log(set)//set{3,2,ziksang}
        console.log(set.has(3)) //true
        console.log(set.delete(2))  //true
        console.log(set)   //set{3,ziksang}
        console.log(set.clear()) //undefined
        console.log(set) //set{}

1.我們new出Set構造函數的實列對象進行一個一個add進行添加,但是添加了兩個同類型同樣值 的2 !最后打印出來同樣的一個會被去除
2.set.has()是進行對set數據結構中成員是否存在的判斷
3.刪除set數據結構中成員
4set.clear()是進行清除所有成員,set實列也因此成為了一個空對象


不同對比的例子,看看Object和Set兩個數據結構判斷方式不同

        let obj={
            name : "ziksang",
            age : 22
        }
        let set = new Set(["name",22])
        if(obj.name){
            console.log("在對象里有name這個健值")
        }
        if(set.has("name")){
            console.log("set數據結構中有name這個成員")
        }

提示

1.[阮一峰]用obj[somename]來判斷是否對象里有這個健,打出來是undefined,以上修正了一下
2.判斷set數據結構中是否有某個成員,用set.has()來判斷


另外再介紹一下另一種數組去重方式

Array.from()是es6數組中新帶的一個方法

        function demo(array){
            return Array.from(new Set(array))
        }
        let result = demo([1,1,2,2,3])
        console.log(result)//1,2,3

Array.from是什么鬼以后具體講到es6數組我給大家講講,我現在只知其一,不知其二,講不透徹的就不給大家講


遍歷操作
Set結構的實例有四個遍歷方法,可以用于遍歷成員。

keys():返回鍵名的遍歷器
values():返回鍵值的遍歷器
entries():返回鍵值對的遍歷器
forEach():使用回調函數遍歷每個成員
需要特別指出的是,Set的遍歷順序就是插入順序。這個特性有時非常有用,比如使用Set保存一個回調函數列表,調用時就能保證按照添加順序調用。

keys方法、values方法、entries方法返回的都是遍歷器對象,因為set沒有健名只有健值 ,所以健名和健值可以說是同一個值 ,keys和values返回的都是同一個值

       let set  = new Set([1,2,3,4])
       for(item of set.keys()){
           console.log(item) //1,2,3,4
       }
       for(item of set.values()){
           console.log(item) //1,2,3,4
       }
       for(item of set.entries()){
           console.log(item) //[1,1],[2,2],[3,3],[4,4]
           console.log(typeof item)//都是object對象
       }

1.keys,values,entries()返回的都是遍歷器對象
2.entries返回的是健值對,因為為健和值都是一樣的,所以里面兩個也一樣,但是返回出來是是一個對象,本值 上是一個類數組對象


Set結構的實例默認可遍歷,它的默認遍歷器生成函數就是它的values方法。第一個張圖我也打印出prototype原型上的方法和屬性里,里面的symbol.iterator里是values()所以也可以直接for of Set構造函數返回的實例

Set.prototype[Symbol.iterator] === Set.prototype.values
// true
       let set  = new Set([1,2,3,4])
       for(item of set){
           console.log(item) //1,2,3,4
       }

可以看出我們直接遍歷SET實例和調用value()返回的遍歷器對象是一樣的


forEach()

Set結構的實例的forEach方法,用于對每個成員執行某種操作,沒有返回值。

       let set  = new Set([1,2,3,4])
       set.forEach(function(value,key){
           console.log(value*key) //1,4,9,16
       })


上面代碼說明了,對set實例里的健和值互乘,其實value和key都是一個值


數組的map和filter方法也可以用set上

       let set  = new Set([1,2,3])
       set = new Set([...set].map(item => item*2))
       console.log(set) //{2,4,6}
       set2 = new Set([...set].filter(item =>item>3))
       console.log(set2)//{4,6}

給大家解釋一下用了那些關鍵方法
1[...set]把set實例進行轉成數組再用map方法把線個值乘2給返回當作Set函數里的成員
2.filter方法也是同理,只是對數組 的值 進行篩選再返回


因此使用Set可以很容易地實現并集(Union)、交集(Intersect)和差集(Difference)。
1.并集Union

        let a = new Set([1,2,3,4,5])
        let b = new Set([1,2,3,6,7])
        let set = new Set([...a,...b])
        console.log(set) //1,2,3,4,5,6,7

上面把a,b里遍歷出來在放入數組,再用set的特性進行去重

2.交集

        let a = new Set([1,2,3,4,5])
        let b = new Set([1,2,3,6,7])
        let intersect = new Set([...a].filter(x => b.has(x)))
        console.log(intersect) //{1,2,3}

上面是把a進行轉化成數組用filter進行過濾,過濾的返回結果是b里面有的值

差集

        let a = new Set([1,2,3,4,5])
        let b = new Set([1,2,3,6,7])
        let intersect = new Set([...a].filter(x => !b.has(x)))
        console.log(intersect) //{4,5}

上面是把a進行轉化成數組用filter進行過濾,過濾的返回結果是b里面沒有的值

如果想在遍歷操作中,同步改變原來的Set結構,目前沒有直接的方法,但有兩種變通方法。一種是利用原Set結構映射出一個新的結構,然后賦值給原來的Set結構;另一種是利用Array.from方法。

// 方法一
let set = new Set([1, 2, 3]);
set = new Set([...set].map(val => val * 2));
// set的值是2, 4, 6

// 方法二
let set = new Set([1, 2, 3]);
set = new Set(Array.from(set, val => val * 2));
// set的值是2, 4, 6

第一個方法本質上是把set重新進行賦值,先把原先的set里面的成為用[...set]化為數組再用map來進行重新操作再返回給set構造函數的成員

第二個方法等我弄懂了再告訴大家

這里我大部分都是按著阮一鋒老師的書籍來進行分析,講的好的我就記錄下來,再用更白的話跟大家講,有些不清楚說的模糊 的地方也更清楚的跟大家解釋明白了,接下來我會把阮一鋒老師 ES6所有的知識點都給大家搞明白,搞透徹

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1.Set 基本用法 ES6提供了新的數據結構Set。它類似于數組,但是成員的值都是唯一的,沒有重復的值。Set本...
    雨飛飛雨閱讀 1,873評論 0 7
  • 一、快速配置安裝zabbix3.2 1、本地zabbix源, 本地zabbix源配置 添加zabbix本地yum源...
    泡菜愛上WaSabi閱讀 289評論 0 0
  • 無聊的人問你無聊時干什么,奈何你也是個無聊的人,你該怎么回答。有時候日子過著過著怎么就無聊了呢,看著其他人的快樂生...
    always1991閱讀 343評論 0 0
  • 滿天星星在閃爍,墜入深藍的愛河。 那顆是你那顆我,愛河深深不可測。
    老槐樹閱讀 181評論 1 2