Javascript 为什么map.has()为已删除对象返回false?

Javascript 为什么map.has()为已删除对象返回false?,javascript,Javascript,让john={name:“john”}; 设map=newmap(); map.set(john,“…”); 设weakmap=newweakmap(); weakmap.set(john,“…”); console.log(map.has(john));//真的 console.log(weakmap.has(john));//真的 john=null; console.log(map.has(john));//假线A console.log(weakmap.has(john));//虚线B

让john={name:“john”};
设map=newmap();
map.set(john,“…”);
设weakmap=newweakmap();
weakmap.set(john,“…”);
console.log(map.has(john));//真的
console.log(weakmap.has(john));//真的
john=null;
console.log(map.has(john));//假线A
console.log(weakmap.has(john));//虚线B
console.log(map);//映射{{…}→ “…”}行C

console.log(weakmap);//弱映射{{…}→ “…”}D行
通过键入
john=null
您将用指向
null
的新指针替换旧指针,并且您不能再访问以前的
john
以将其用作
映射的键,因此您观察到的情况完全正常。
Map
的键是
john
值,而不是变量的名称

john
的上一个值未被垃圾收集,因为仍然从
Map
引用,并且您仍然可以使用以下选项之一检索它:


通过键入
john=null
您将用指向
null
的新指针替换旧指针,并且您无法再访问以前的
john
以将其用作
映射的键,因此您观察到的情况完全正常。
Map
的键是
john
值,而不是变量的名称

john
的上一个值未被垃圾收集,因为仍然从
Map
引用,并且您仍然可以使用以下选项之一检索它:


    • john=null
      不会删除以前由
      john
      引用的对象,它将变量
      john
      设置为指向
      null
      ,而不是它以前指向的对象

      当您运行
      console.log(map.has(john))
      ,现在
      john
      设置为
      null
      ,这相当于运行
      console.log(map.has(null))。映射没有由
      null
      键入的条目,因此它返回false

      我知道即使垃圾收集器删除了一个对象,这个对象也可以在地图中使用


      这是不正确的。垃圾回收器不会删除仍有强引用指向它的对象。即使您将
      john
      设置为
      null
      ,删除对对象的引用,您的映射仍然有一个指向它的键,因此垃圾收集器不会将其从内存中释放出来。如果您只有WeakMap,那么它可能在垃圾回收器下次运行时被垃圾回收,但这不会很快发生,您无法在同一代码块中观察到它。

      john=null
      不会删除以前由
      john
      引用的对象,它将变量
      john
      设置为指向
      null
      ,而不是它以前指向的对象

      当您运行
      console.log(map.has(john))
      ,现在
      john
      设置为
      null
      ,这相当于运行
      console.log(map.has(null))。映射没有由
      null
      键入的条目,因此它返回false

      我知道即使垃圾收集器删除了一个对象,这个对象也可以在地图中使用


      这是不正确的。垃圾回收器不会删除仍有强引用指向它的对象。即使您将
      john
      设置为
      null
      ,删除对对象的引用,您的映射仍然有一个指向它的键,因此垃圾收集器不会将其从内存中释放出来。如果您只有弱映射,那么它可能会在垃圾收集器下一步运行时被垃圾收集—但这不会很快发生,您无法在同一代码块中观察到它。

      看起来您想要演示常规映射和弱映射之间的区别。但它不起作用的原因很简单:

      您无法检测对象是否是通过JavaScript代码进行垃圾收集的,因为这会使您仍然需要检查引用。但是如果你有一个引用,那么它不可能被垃圾收集

      关于你的问题:

      我知道即使垃圾收集器删除了一个对象,这个对象也可以在地图中使用

      事实并非如此。如果它位于常规映射中,则构成对对象的引用,因此不能对其进行垃圾收集

      所以我希望在“行A”上输出“true”,但它打印false我缺少什么

      没有办法编写JavaScript代码来为映射打印
      true
      ,为弱映射打印
      false
      。您的测试有缺陷,因为您将
      john
      更改为其他对象,因此您的
      .has(john)
      调用与原始对象无关,而是与您给此变量的新值有关。因此,这些结果与您存储在地图中的原始对象无关

      为什么我在C行和D行看到john object?如果A行和B行的结果为假,为什么C行和D行打印john对象

      因为
      false
      输出不是关于原始john对象,而是关于
      null


      还要意识到,console在向您显示WeakMap的内容方面帮了您一个大忙,就像这样,而在JavaScript代码中,您无法迭代WeakMap的所有内容。

      看起来您想要演示常规映射和弱映射之间的区别。但它不起作用的原因很简单:

      您无法检测对象是否是通过JavaScript代码进行垃圾收集的,因为这会使您仍然需要检查引用。但是,如果你有一个推荐人,那么这是不可能的