zoukankan      html  css  js  c++  java
  • ES6

    1.Set类型简介

    ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值

    Set本身是一个构造函数,用来生成Set数据结构

    1 const s = new Set();
    2 [1,2,3,4,4,3,2,1].forEach( e => s.add(e))
    3 
    4 for(let i of s){
    5     console.log(i);
    6 }
    7 // 1,2,3,4

     上面代码通过add()方法向Set结构加入成员,结果表明Set结构不会添加重复的值

    Set函数可以接受一个数组(或者具有Iterable接口的其他数据结构)作为参数,用来初始化

     1 // 例一
     2 const set = new Set([1, 2, 3, 4, 4]);
     3 [...set]
     4 // [1, 2, 3, 4]
     5 
     6 // 例二
     7 const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
     8 items.size // 5
     9 
    10 // 例三
    11 const set = new Set(document.querySelectorAll('div'));
    12 set.size // 56
    13 
    14 // 类似于
    15 const set = new Set();
    16 document
    17  .querySelectorAll('div')
    18  .forEach(div => set.add(div));
    19 set.size // 56

    上面的办法展示了一种去除数组重复成员的方法:

    const arr = [1,1,3,3,4,4,2]
    const newArr = [...new Set(arr)]
    newArr  // [1, 3, 4, 2]

    或者也可以用于去除字符串里面的重复字符:

    let str = "hello world"
    
    let newStr = [...new Set(str.split(""))].join("")
    
    newStr  // "helo wrd"

    向Set加入值得时候,不会发生类型转换,所以 5 和 "5" 是两个不同的值。Set内部判断两个值是否不同使用的算法叫做'Same-Value-zero equality",它类似于精确相等运算符(===)。主要的区别是向 Set 加入值时认为NaN等于自身,而精确相等运算符认为NaN不等于自身。

    let set = new Set();
    let a = NaN;
    let b = NaN;
    set.add(a);
    set.add(b);
    set // Set {NaN}

    上面代码向 Set 实例添加了两次NaN,但是只会加入一个。这表明,在 Set 内部,两个NaN是相等的。

    另外,两个对象总是不相等的。

    let set = new Set()
    
    set.add({})
    set.add({})
    
    set.size  // 2

    上面代码表示,由于两个空对象不相等,所以它们被视为两个值。

    2.Set实例的属性和方法

    查看Set类型的原型对象可以看到Set结构的实例有以下属性。

    (1)属性

    • Set.prototype.constructor:构造函数,默认就是Set函数。
    • Set.prototype.size:返回Set实例的成员总数。

    (2)方法

    Set实例的方法分为两大类:

    • 操作方法(用于操作数据)
      • Set.prototype.add(value):添加某个值,返回Set结构本身
      • Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功
      • Set.prototype.has(value):返回一个布尔值,表示该值是否为Set的成员
      • Set.prototype.clear():清除所有成员,没有返回值
      • 实例:
        •  1 s.add(1).add(2).add(2);
           2 // 注意2被加入了两次
           3 
           4 s.size // 2
           5 
           6 s.has(1) // true
           7 s.has(2) // true
           8 s.has(3) // false
           9 
          10 s.delete(2);
          11 s.has(2) // false
    • 遍历方法(用于遍历成员)
      • Set.prototype.keys():返回键名的遍历器
      • Set.prototype.values():返回键值的遍历器
      • Set.prototype.entries():返回键值对的遍历器
        • 实例:
          •  1     let set = new Set(['red', 'green', 'blue'])
             2 
             3     for (let item of set.keys()) {
             4         console.log(item);
             5     }
             6     // red
             7     // green
             8     // blue
             9 
            10     for (let item of set.values()) {
            11         console.log(item);
            12     }
            13     // red
            14     // green
            15     // blue
            16 
            17     for (let item of set.entries()) {
            18         console.log(item);
            19     }
            20     // ["red", "red"]
            21     // ["green", "green"]
            22     // ["blue", "blue"]
        • 说明:entries方法返回的遍历器,同时包括键名和键值,所以每次输出一个数组,它的两个成员完全相等。
      • Set.prototype.forEach():使用回调函数遍历每个成员Set 结构的实例与数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值。注意:Set的遍历顺序就是插入顺序
      • 实例:
        • 1 let set = new Set([1, 4, 9]);
          2 set.forEach((value, key) => console.log(key + ' : ' + value))
          3 // 1 : 1
          4 // 4 : 4
          5 // 9 : 9
        • 上面代码说明,forEach方法的参数就是一个处理函数。该函数的参数与数组的forEach一致,依次为键值、键名、集合本身(上例省略了该参数)。这里需要注意,Set 结构的键名就是键值(两者是同一个值),因此第一个参数与第二个参数的值永远都是一样的。
      • 遍历方法的应用:
        • 扩展运算符和 Set 结构相结合,就可以去除数组的重复成员。
          • let arr = [3, 5, 2, 2, 5, 5];
            let unique = [...new Set(arr)];
            // [3, 5, 2]
        • 数组的mapfilter方法也可以间接用于 Set 了。
          • let set = new Set([1, 2, 3]);
            set = new Set([...set].map(x => x * 2));
            // 返回Set结构:{2, 4, 6}
            
            let set = new Set([1, 2, 3, 4, 5]);
            set = new Set([...set].filter(x => (x % 2) == 0));
            // 返回Set结构:{2, 4}
        • 使用Set实现并集(Union)、交集(Intersect)、差集(Difference):
          • let a = new Set([1,2,3])
            let b = new Set([3,4,5])
            
            // 并集:
            let union = new Set([...a,...b])
            // union : {1, 2, 3, 4, 5}
            
            // 交集
            let intersect = new Set([...a].filter( e => b.has(e) ))
            // {3}
            
            // 差集 (a 相对于 b的差集)
            let difference = new Set([...a].filter(e => !b.has(e)))
            // {1, 2}
      • 如果想在遍历操作中,同步改变原来的 Set 结构,目前没有直接的方法,但有两种变通方法。一种是利用原 Set 结构映射出一个新的结构,然后赋值给原来的 Set 结构;另一种是利用Array.from方法。
        • 1 // 方法一
          2 let set = new Set([1, 2, 3]);
          3 set = new Set([...set].map(val => val * 2));
          4 // set的值是2, 4, 6
          5 
          6 // 方法二
          7 let set = new Set([1, 2, 3]);
          8 set = new Set(Array.from(set, val => val * 2));
          9 // set的值是2, 4, 6

    3.WeakSet

    WeakSet结构与Set类似,也是不重复的值的集合。但是与Set有两个区别。

     (1)WeakSet的成员只能是对象,不能是其他类型的值

    const ws = new WeakSet();
    ws.add(1)
    // TypeError: Invalid value used in weak set
    ws.add(Symbol())
    // TypeError: invalid value used in weak set

     (2)WeakSet中的对象都是弱引用,即垃圾回收机制不考虑WeakSet对该对象的引用

    也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。

    这是因为垃圾回收机制依赖引用计数,如果一个值的引用次数不为0,垃圾回收机制就不会释放这块内存。结束使用该值之后,有时会忘记取消引用,导致内存无法释放,进而可能会引发内存泄漏。WeakSet 里面的引用,都不计入垃圾回收机制,所以就不存在这个问题。因此,WeakSet 适合临时存放一组对象,以及存放跟对象绑定的信息。只要这些对象在外部消失,它在 WeakSet 里面的引用就会自动消失。

    由于上面这个特点,WeakSet 的成员是不适合引用的,因为它会随时消失。另外,由于 WeakSet 内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不一样的,而垃圾回收机制何时运行是不可预测的,因此 ES6 规定 WeakSet 不可遍历。

  • 相关阅读:
    一个、说到所有的扩展指标
    时序图、流程图
    流程图总结
    UML活动图与流程图的区别
    类图与对象图
    app的描述-软件的描述
    UML的目标
    软件建模的用途
    Android中如何使用Intent在Activity之间传递对象[使用Serializable或者Parcelable]
    Serializable 和 Parcelable 区别
  • 原文地址:https://www.cnblogs.com/codexlx/p/14345940.html
Copyright © 2011-2022 走看看