Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在WeakMap中使用DOM节点作为键_Javascript_Weakmap - Fatal编程技术网

Javascript 在WeakMap中使用DOM节点作为键

Javascript 在WeakMap中使用DOM节点作为键,javascript,weakmap,Javascript,Weakmap,在使用WeakMap时,我遇到了一个非常令人困惑的场景:假设我有一个DOM节点,其中包含一些我想要存储的数据,我使用元素/节点本身作为键,将任意数据作为值存储在WeakMap中 在从WeakMap存储和检索条目之间,DOM节点发生了变化:比如说,它的id属性被更新。我希望.get()将返回未定义的,因为节点已经发生了变异,但它仍然以某种方式返回它 但是,当我销毁DOM树中的节点并重新渲染它时,即使不更改它的任何属性或属性,它现在在存储时也被视为WeakMap中的新元素 我的问题是:为什么在Wea

在使用
WeakMap
时,我遇到了一个非常令人困惑的场景:假设我有一个DOM节点,其中包含一些我想要存储的数据,我使用元素/节点本身作为键,将任意数据作为值存储在
WeakMap

在从
WeakMap
存储和检索条目之间,DOM节点发生了变化:比如说,它的
id
属性被更新。我希望
.get()
将返回
未定义的
,因为节点已经发生了变异,但它仍然以某种方式返回它

但是,当我销毁DOM树中的节点并重新渲染它时,即使不更改它的任何属性或属性,它现在在存储时也被视为
WeakMap
中的新元素

我的问题是:为什么在
WeakMap
中更改DOM节点(用作存储任意数据的键)时不返回
undefined
?下面是一个概念验证示例,其中包含再现行为的说明:

  • 单击“存储元素”
  • 单击“检索元素”以验证元素确实存储在
    WeakMap
  • 点击“变异元素”。元素应该更新其
    id
    属性
  • 单击“Retrieve element”:即使元素已经发生了变化,它仍然可以检索与原始元素一起设置的值
  • 单击“销毁并重新创建元素”。节点从DOM中删除,其
    outerHTML
    用于创建外观相同的元素
  • 单击“Retrieve element”:
    WeakMap
    正确地报告没有找到任何内容,因为我们使用了一个全新的DOM节点作为键
  • const map=new WeakMap();
    //在WeakMap中存储元素
    document.getElementById('set')。addEventListener('click',()=>{
    const el=document.querySelector(“#content>div”);
    地图集(el,el.outerHTML);
    log('WeakMap中存储的元素');
    });
    //从WeakMap检索元素
    document.getElementById('get').addEventListener('click',()=>{
    const el=document.querySelector(“#content>div”);
    const elHTML=map.get(el);
    如果(elHTML)
    log(`Element在WeakMap中找到,它的数据:${elHTML}`);
    其他的
    log('Weakmap!'中未找到元素!');
    });
    //改变DOM节点,比如说给它一个新的唯一ID
    设n=0;
    document.getElementById('mutate').addEventListener('click',()=>{
    document.querySelector('#content>div').id=`test${n}`;
    log(`Element ID更新为:“test${n}`);
    n++;
    });
    //摧毁并重建元素
    document.getElementById('destroy_and_recreate')。addEventListener('click',()=>{
    const target=document.querySelector(“#content>div”);
    const targetHTML=target.outerHTML;
    target.remove();
    document.getElementById('content').innerHTML=targetHTML;
    log(“元素已销毁并重新创建”);
    });
    
    
    Lorem ipsum dolor sit amet
    
    存储元素 检索元素
    变异元素
    销毁并重新创建元素
    的原因与
    {}!={}
    ;两个对象是否具有相同的属性并不重要,或者如果它们发生了更改,也不重要,重要的是它们是否实际上是相同的对象—从技术上讲,是内存中的相同位置。如果要按特性和值比较对象,请使用Lodash中的深度相等函数

    为什么@charlietfl删除了他的答案,他基本上是正确的。基本上,DOM节点只是一个嵌套对象。当您更新属性时,您是在对其进行变异,而不是对其在内存中的位置进行变异。该对象需要可用于垃圾收集,以便WeakMap释放其密钥,从文档树中删除DOM会导致此问题。出于同样的原因,WeakMap键是不可枚举的:只是在前面的注释中添加了一个注释:从DOM树中删除元素不一定会将其标记为垃圾回收,只有当DOM树是该对象引用的唯一位置时才会出现这种情况。在remove&recreate示例中,两个元素对象是两个完全不同的实例。