RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1159227
Accepted
Burg
Burg
Asked:2020-07-30 23:22:38 +0000 UTC2020-07-30 23:22:38 +0000 UTC 2020-07-30 23:22:38 +0000 UTC

什么时候使用 Set a when WeakSet

  • 772

何时使用 Set a vs. WeakSet,有什么区别,哪个更好,为什么?

var arr = [1, 2, 3, 4, 5]; 

和

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

和

var weak_set = new WeakSet([1, 2, 3, 4, 5]);

文档已经写好,但不清楚应该在哪里使用以及为什么。

javascript
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Vasily
    2020-07-31T01:03:34Z2020-07-31T01:03:34Z

    集合对象是可以包含任何类型数据的唯一值的集合。

    让我们做一个简单的集合来看看:

    const numbers = [7, 1, 1, 2, 3, 5, 8] 
    
    const set = new Set(numbers)
    
    console.log(set)
    // Set { 7, 1, 2, 3, 5, 8 }
    

    如我们所见,它只包含 numbers 数组中的唯一值,它们的顺序保持不变。


    这使得 Set 对象成为从数组中删除重复项的最简单方法之一:

    const uniqueNumbers = [...new Set(numbers)]
    console.log(uniqueNumbers)
    // [ 7, 1, 2, 3, 5, 8 ]
    

    这正是它的关键特性,无论传递什么值,它们都只会存储在单个实例中。


    让我们使用add()方法检查这一点:

    set.add(100)
    console.log(set)
    // Set { 7, 1, 2, 3, 5, 8, 100 }
    
    set.add(7)
    console.log(set)
    // Set { 7, 1, 2, 3, 5, 8, 100 }
    // наш сет не изменился так как 
    // уже содержал в себе значение 7
    

    并使用size属性记住这个集合的大小:

    const setSize = set.size
    console.log(setSize)
    // 7
    

    可以在此处查看方法和属性的完整列表。

    迭代协议是为 Set 对象定义的,所以我们可以像map一样迭代它们:

    for (let item of set) {
      console.log(item) 
    }
    
    for (let key of set.keys()) {
      console.log(key) 
    }
    
    for (let value of set.values()) {
      console.log(value) 
    }
    
    // все эти варианты вернут 
    // одинаковый результат:
    // 7
    // 1
    // 2
    // 3
    // 5
    // 8
    // 100
    

    如果我们使用entry()方法,我们会得到:

    for (let entry of set.entries()) {
      console.log(entry) 
      // [ 7, 7 ]
      // [ 1, 1 ]
      // [ 2, 2 ]
      // [ 3, 3 ]
      // [ 5, 5 ]
      // [ 8, 8 ]
      // [ 100, 100 ]
    }
    

    这样做是为了Set与Map向后兼容。


    是什么让 WeakSet 与众不同

    1. 在普通集合中,我们可以存储任何类型的数据,但在弱集合中只能存储对象;

    2. 在弱集中,只有add()、has()、delete()和clear()方法可供我们使用;

    3. 垃圾收集器会自动删除没有任何外部引用的对象:

      const countries = [
        {
          country: "Russia"
        },
        {
          country: "Australia"
        }
      ]
      
      const weakSet = new WeakSet()
      
      weakSet.add(countries[0])
      
      let hasRussia = weakSet.has(countries[0])
      console.log(hasRussia)
      // true
      
      countries.splice(0, 1)
      
      hasRussia = weakSet.has(countries[0])
      console.log(hasRussia)
      // false
      
      // из за особенностей реализации мы точно не знаем 
      // когда будет удален конкретный объект, поэтому:
      
    4. 您不能查看 WeakSet'e 中存储的内容:

      console.log(weakSet)
      // WeakSet { <items unknown> }
      
    5. 它的大小是未知的(分别没有size属性);

    6. 由于上述原因,它们是不可迭代的。

    什么和何时使用:

    我不假装是真的,如果您不同意下面写的内容,请在评论中制定您自己的看法。

    集合与数组

    如果您不需要重复和/或速度很重要,请使用集合而不是数组(集合更快,这在大型集合中尤其明显)。

    集与弱集

    如果您只处理对象并且需要提高处理数据的效率,请使用弱集。在上面的国家/地区示例中,您可以看到从数组中删除一个对象也会自动将其从 WeakSet 中删除。

    • 15
  2. Sergei Kirjanov
    2020-08-22T04:47:17Z2020-08-22T04:47:17Z

    我会补充我的想法。

    为什么需要它WeakSet?为此,您可以首先考虑为什么需要WeakMap.

    假设有一个特定的对象——一个产品。并且有一个特定的可视化工具可以为这个产品形成图片。整形过程繁重,渲染器要缓存图像。他可以在产品中放一张图片,但是:

    • 理想情况下,图片对于可视化者来说是私有的,只有他会使用它
    • 产品可以是不可变的
    • 如果不再需要可视化器,则图片将与产品一起挂在内存中

    渲染器可以为自己保存图像,但事实证明:

    • 如果不再需要该产品,则图片将与可视化工具一起挂在内存中。

    WeakMap在这一点上,渲染器作为一种处理对象生命周期交集的方式来拯救。仅当(可视化器和产品)都处于活动状态时,图像才会存储在WeakMap渲染器中。

    这WeakSet只是一对 k WeakMap,好吧,既然有Mapand Set,那么为了对称而拥有它是合乎逻辑的。您可以存储对象的简单关系(某种喜欢)。

    至于什么Set比数组快,多半是个意外。在浏览器的下一个版本中,它可能会变得相反,我不会依赖这个。

    如果 WeakSet 中存储的对象没有外部引用,则垃圾收集器将删除该对象。

    我们无法检查它是否已经(立即)删除了该对象,因为我们只使用has-th 进行检查,这需要对该对象的引用。如果有引用,那么收集器不会删除该对象。所以可以说它最终会在某个时候删除该对象。

    • 0

相关问题

  • 第二个 Instagram 按钮的 CSS 属性

  • 由于模糊,内容不可见

  • 弹出队列。消息显示不正确

  • 是否可以在 for 循环中插入提示?

  • 如何将 JSON 请求中的信息输出到数据表 Vuetify vue.js?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5