Javascript 知识点逐步分析与解剖Web前端之路技术干货

ECMAscript6 中Set数据结构

2017-01-30  本文已影响128人  Ziksang

大家好混元霹雳手Ziksang又来了,给大家讲讲es6,Set这个新的数据结构

大年初三,先给大家拜个年,我知道我的拜方式错了!!红包即将打到你的支付宝中,请接收!

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所有的知识点都给大家搞明白,搞透彻

上一篇下一篇

猜你喜欢

热点阅读