zoukankan      html  css  js  c++  java
  • 深入理解 ES6 新增的数据结构 Set 与 WeakSet

    一、Set

    1、Set 的基本用法

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

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

    var s = new Set();
    
    [2, 3, 5, 4, 5, 2, 2].map(x => s.add(x));
    
    for (let i of s) {
      console.log(i);
    }
    // 2 3 5 4
    

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

    Set 函数可以接受一个数组(或类数组)作为参数,用来初始化

    // 例一
    var set1 = new Set([1, 2, 3, 3, 4]);
    
    set1      // {1, 2, 3, 4}
    set1.size // 4
    [...set1] // [1, 2, 3, 4]
    
    // 例二
    const divArr = [...document.querySelectorAll('div')]
    var set2 = new Set(divArr);
    
    set2      // {div.div1, div.div2, div.div3}
    set2.size // 3
    [...set2] // [div.div1, div.div2, div.div3]
    

    上面代码中,例一是 Set 函数接受数组作为参数,例二是接受类数组作为参数

    2、Set 对数组进行去重

    上面代码中,也展示了一种去除数组重复成员的方法

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

    Array.from 方法也可以将 Set 结构转为数组

    var set = new Set([1, 2, 3, 3, 4]);
    
    Array.from(set) // [1, 2, 3, 4]
    

    另外,向 Set 加入值时,不会发生类型转换,所以 5 和 "5" 是两个不同的值
    Set 内部判断两个值是否不同,使用的算法叫做 “Same-value equality”,类似于 ===,区别在于 “Same-value equality”NaN 等于自身,而 === 认为 NaN 不等于自身

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

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

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

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

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

    3、Set 实例的属性

    Set 实例的属性包括:

    Set.prototype.constructor

    构造函数,默认就是 Set 函数

    var set = new Set([1, 2, 3]);
    
    set.constructor // Set() { [native code] }=
    

    Set.prototype.size

    返回 Set 实例的成员总数

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

    4、Set 实例的操作方法

    ① add(value)

    添加某个值,返回 Set 结构本身

    var set1 = new Set([1, 2, 3]);
    var set2 = set1.add(4)
    
    set1  // Set(4) {1, 2, 3, 4} 
    set2  // Set(4) {1, 2, 3, 4} 
    

    ② delete(value)

    删除某个值,返回一个布尔值,表示删除是否成功

    var set1 = new Set([1, 2, 3]);
    var set2 = set1.delete(2)
    var set3 = set1.delete(4)
    
    set1  // {1, 3}
    set2  // true
    set3  // false
    

    ③ has(value)

    返回一个布尔值,表示该值是否为 Set 的成员

    var set1 = new Set([1, 2, 3]);
    var set2 = set1.has(2)
    var set3 = set1.has(4)
    
    set1  // Set(3) {1, 2, 3}
    set2  // true
    set3  // false
    

    ④ clear()

    清除所有成员,没有返回值

    var set1 = new Set([1, 2, 3]);
    var set2 = set1.clear()
    
    set1  // Set(0) {}
    set2  // undefined
    

    5、Set 实例的遍历方法

    ① keys()

    返回键名的遍历器

    let set = new Set(['red', 'green', 'blue']);
    
    for (let item of set.keys()) {
      console.log(item);
    }
    // red
    // green
    // blue
    

    ② values()

    返回键值的遍历器

    let set = new Set(['red', 'green', 'blue']);
    
    for (let item of set.values()) {
      console.log(item);
    }
    // red
    // green
    // blue
    

    Set 结构的默认遍历器生成函数就是它的 values 方法
    因此,可以省略 values 方法,直接用 for...of 循环遍历 Set

    let set = new Set(['red', 'green', 'blue']);
    
    for (let x of set) {
      console.log(x);
    }
    // red
    // green
    // blue
    

    ③ entries()

    返回键值对的遍历器,每次输出一个数组,两个成员完全相等

    let set = new Set(['red', 'green', 'blue']);
    
    for (let item of set.entries()) {
      console.log(item);
    }
    // ["red", "red"]
    // ["green", "green"]
    // ["blue", "blue"]
    

    ④ forEach()

    使用回调函数遍历每个成员,用于对每个成员执行某种操作,没有返回值

    let set = new Set([1, 2, 3]);
    set.forEach((value, key) => console.log(value * 2))
    // 2
    // 4
    // 6
    

    6、Set 遍历的应用

    ① 并集(Union)

    let a = new Set([1, 2, 3]);
    let b = new Set([3, 4, 5]);
    
    let union = new Set([...a, ...b]);
    
    union // Set(5) {1, 2, 3, 4, 5}
    

    ② 交集(Intersect)

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

    ③ 差集(Difference)

    let a = new Set([1, 2, 3]);
    let b = new Set([3, 4, 5]);
    
    let difference = new Set([...a].filter(x => !b.has(x)));
    
    difference // Set(2) {1, 2}
    

    二、WeakSet

    1、WeakSet 的基本用法

    WeakSet 是一个构造函数,可以使用 new 命令,创建 WeakSet 数据结构

    var ws = new WeakSet();
    
    ws // WeakSet {}
    

    作为构造函数,WeakSet 可以接受一个数组或类数组的对象作为参数,该数组的所有成员,都会自动成为 WeakSet 实例对象的成员

    var a = [[1, 2], [3, 4]];
    var ws = new WeakSet(a);
    
    ws // WeakSet {Array(2), Array(2)}
    

    上面代码中,a 是一个数组,它有两个成员,也都是数组
    a 作为 WeakSet 构造函数的参数,a 的成员会自动成为 WeakSet 的成员

    2、WeakSet 与 Set 的区别

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

    ① WeakSet 的成员只能是对象,而不能是其他类型的值

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

    上面代码试图向 WeakSet 添加一个数值和 Symbol 值,结果报错,因为 WeakSet 只能放置对象

    ② WeakSet 中的对象都是弱引用

    即垃圾回收机制不考虑 WeakSet 对该对象的引用
    也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中
    这个特点意味着,无法引用 WeakSet 的成员,因此 WeakSet 是不可遍历的

    3、WeakSet 实例的操作方法

    ① WeakSet.prototype.add(value)

    WeakSet 实例添加一个新成员

    var ws = new WeakSet();
    var obj = {};
    
    ws.add(window);
    ws.add(obj);
    
    ws  // WeakSet {{…}, Window}
    

    输出结果详情:

    ② WeakSet.prototype.delete(value)

    清除 WeakSet 实例的指定成员

    var ws = new WeakSet();
    var obj = {};
    
    ws.add(window);
    ws.add(obj);
    
    ws  // WeakSet {{…}, Window}
    
    ws.delete(window);
    
    ws  // WeakSet {{…}}
    

    ③ WeakSet.prototype.has(value)

    返回一个布尔值,表示某个值是否在 WeakSet 实例之中

    var ws = new WeakSet();
    var obj = {};
    
    ws.add(window);
    
    ws.has(window); // true
    ws.has(obj);    // false
    

    注意

    • WeakSet 没有 size 属性,没有办法遍历它的成员
    • WeakSet 不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保证成员的存在,很可能刚刚遍历结束,成员就取不到了
    • WeakSet 的一个用处,是储存 DOM 节点,而不用担心这些节点从文档移除时,会引发内存泄漏
  • 相关阅读:
    HDU 5585 Numbers
    HDU 3308 LCIS
    POJ 2991 Crane
    POJ 1436 Horizontally Visible Segments
    POJ 3667 Hotel
    HaiHongOJ 1003 God Wang
    【SDOI 2008】 递归数列
    5月19日省中提高组题解
    【HDU 1588】 Gauss Fibonacci
    【POJ 3233】Matrix Power Series
  • 原文地址:https://www.cnblogs.com/Leophen/p/14794271.html
Copyright © 2011-2022 走看看