草庐IT

javascript - ES6 集合、WeakSet、Map 和 WeakMap

coder 2025-02-16 原文

已经有一些关于 map 和弱 map 的问题,像这样:What's the difference between ES6 Map and WeakMap?但我想问一下在什么情况下我应该赞成使用这些数据结构?或者当我偏爱其中一个时我应该考虑什么?

数据结构示例来自:https://github.com/lukehoban/es6features

// Sets
var s = new Set();
s.add("hello").add("goodbye").add("hello");
s.size === 2;
s.has("hello") === true;

// Maps
var m = new Map();
m.set("hello", 42);
m.set(s, 34);
m.get(s) == 34;

// Weak Maps
var wm = new WeakMap();
wm.set(s, { extra: 42 });
wm.size === undefined

// Weak Sets
var ws = new WeakSet();
ws.add({ data: 42 });
// Because the added object has no other references, it will not be held in the set

奖金。以上哪些数据结构会产生相同/相似的结果: let hash = object.create(null); hash[index] = something;

最佳答案

这包含在 §23.3 中规范:

If an object that is being used as the key of a WeakMap key/value pair is only reachable by following a chain of references that start within that WeakMap, then that key/value pair is inaccessible and is automatically removed from the WeakMap.

所以弱映射中的条目,如果它们的键没有被其他任何东西引用,将在某个时候被垃圾收集回收。

相比之下,Map 持有对其键的引用,如果 map 是唯一引用它们的对象,则可以防止它们被垃圾回收。

MDN puts it like this :

The key in a WeakMap is held weakly. What this means is that, if there are no other strong references to the key, then the entire entry will be removed from the WeakMap by the garbage collector.

WeakSet 也是如此。

...in which situation should I favor the use of this data structures?

任何你不希望你有一个使用键的映射/集合的情况,以防止该键被垃圾收集。以下是一些示例:

  1. 拥有对实例真正私有(private)的特定于实例的信息,如下所示:(注意:此示例来自 2015 年,远早于 private fields 是一个选项。在 2021 年,我会为此使用私有(private)字段。)

    let Thing = (() => {
        var privateData = new WeakMap();
    
        class Thing {
            constructor() {
                privateData[this] = {
                    foo: "some value"
                };
            }
    
            doSomething() {
                console.log(privateData[this].foo);
            }
        }
    
        return Thing;
    })();
    

    作用域函数之外的代码无法访问 privateData 中的数据。该数据由实例本身键入。如果没有 WeakMap,您将不会这样做,因为这会导致内存泄漏,您的 Thing 实例将永远不会被清理。但是 WeakMap 只包含 weak 引用,因此如果您使用 Thing 实例的代码完成了它并释放了它对该实例的引用, WeakMap 不会阻止实例被垃圾回收;相反,实例键入的条目将从映射中删除。

  2. 持有您无法控制的对象的信息。假设您从某个 API 获得了一个对象,您需要记住有关该对象的一些附加信息。您可以向对象本身添加属性(如果它不是密封的),但是向您控制之外的对象添加属性只是自找麻烦。相反,您可以使用以对象为键的 WeakMap 来存储您的额外信息。

  3. WeakSet 的一个用例是跟踪或标记:假设在“使用”一个对象之前,您需要知道该对象过去是否曾经被“使用过”,但是不将其存储为对象上的标志(也许是因为如果它是对象上的标志,其他代码可以看到它[尽管您可以使用私有(private)字段来防止这种情况];或者因为它不是您的对象[所以私有(private)字段不会'帮助])。例如,这可能是某种一次性访问 token 。 WeakSet 是一种无需强制对象保留在内存中的简单方法。

Which of the above data structures will produce the same/similar result of doing: let hash = Object.create(null); hash[index] = something;

这将最接近 Map,因为字符串 index(属性名称)将由对象中的强引用持有(它及其关联的属性将如果没有其他引用它,则不会被回收)。

关于javascript - ES6 集合、WeakSet、Map 和 WeakMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32710432/

有关javascript - ES6 集合、WeakSet、Map 和 WeakMap的更多相关文章

  1. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  2. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  3. ES基础入门 - 2

    ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear

  4. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  5. ruby - 在 ruby​​ 中使用 .try 函数和 .map 函数 - 2

    我需要从json记录中获取一些值并像下面这样提取curr_json_doc['title']['genre'].map{|s|s['name']}.join(',')但对于某些记录,curr_json_doc['title']['genre']可以为空。所以我想对map和join()使用try函数。我试过如下curr_json_doc['title']['genre'].try(:map,{|s|s['name']}).try(:join,(','))但是没用。 最佳答案 你没有正确传递block。block被传递给参数括号外的方法

  6. ruby - 按数字(从大到大)然后按字母(字母顺序)对对象集合进行排序 - 2

    我正在构建一个小部件来显示奥运会的奖牌数。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,以及奖牌计数的“金”、“银”、“铜”。列表应该排序:1.首先是奖牌总数2.如果奖牌相同,按类型分割(金>银>铜,即2金>1金+1银)3.如果奖牌和类型相同,则按字母顺序子排序我正在用ruby​​做这件事,但我想语言并不重要。我确实找到了一个解决方案,但如果感觉必须有更优雅的方法来实现它。这是我做的:使用加权奖牌总数创建一个虚拟属性。因此,如果他们有2个金牌和1个银牌,加权总数将为“3.020100”。1金1银1铜为“3.010101”由于我们希望将奖牌数排序为最高的,因此列表按降序排

  7. ruby - 不能将 `each` 的所有或大多数情况替换为 `map` 吗? - 2

    Enumerable#each和Enumerable#map的区别在于返回的是接收者还是映射后的结果。回到接收者是微不足道的,你通常不需要在each之后继续一个方法链,比如each{...}.another_method(我可能没见过这样的案例。即使你想回到接收者那里,你也可以通过tap来实现)。所以我认为所有或者大部分使用Enumerable#each的情况都可以用Enumerable#map代替。我错了吗?如果我是对的,each的目的是什么?map是否比each慢?编辑:我知道当您对返回值不感兴趣时​​使用each是一种常见的做法。我对这种做法是否存在不感兴趣,但感兴趣的是,除了从

  8. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

    我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

  9. ruby - `map` 比 `each` 快吗? - 2

    map遍历数组是否比each更快?两者有速度差异吗?mapresult=arr.map{|a|a+2}每个result=[]arr.eachdo|a|result.push(a+2)end 最佳答案 我认为是的。我试过这个测试require"benchmark"n=10000arr=Array.new(10000,1)Benchmark.bmdo|x|#Mapx.reportdon.timesdoresult=arr.map{|a|a+2}endend#Eachx.reportdon.timesdoresult=[]arr.each

  10. ruby - 用于 Ruby 哈希的 map_values()? - 2

    我想念Ruby中的Hash方法来仅转换/映射散列值。h={1=>[9,2,3,4],2=>[6],3=>[5,7,1]}h.map_values{|v|v.size}#=>{1=>4,2=>1,3=>3}你如何在Ruby中归档它?更新:我正在寻找map_values()的实现。#moreexamplesh.map_values{|v|v.reduce(0,:+)}#=>{1=>18,2=>6,3=>13}h.map_values(&:min)#=>{1=>2,2=>6,3=>1} 最佳答案 Ruby2.4引入了方法Hash#tran

随机推荐