一个方法真的可以从 window 对象中删除它的父对象吗?

Can a method really delete its parent object from the window object?

在尝试将函数保留在单独的命名空间中并尝试释放不再需要的命名空间消耗的内存时,我无意中编写了这个代码,甚至没有考虑它正在从内部删除命名空间 N它自己的方法之一,N.loader()。起初我在 finally 中有 unload('N'),在意识到只有在注入新脚本后才会执行后,我在注入之前移动了 unload()

即使注入的脚本删除了 window.N,它也会在 finally 执行之前从 N.loader() 方法的最后 .then() 中执行。

因此,我很困惑这是否真的从内存中删除了命名空间及其方法,或者只是让它们无法从剩余的 JS 代码中访问。

您能解释一下这在幕后是如何工作的吗?怎么可能方法执行完还没有删除方法的父对象呢?

谢谢。


 "use strict";
 try {
   window.N = new Object();
   window.N.loader = function() {
     fetch(url, {})
     .then( response => {})
     .then( data => {
         return fetch(url,{});
     })
     .then( response => {
     })
     .then( data => {
       unload('N');
       let d = new DOMParser(),
           b = d.parseFromString( data, 'text/html' );
       // inject new script.
       // console.log( window.N ) => undefined.
     })
     .catch( error => {
       console.error('Error:', error);
     })
     .finally( () => {
       // too late to delete window.N.
       // New script already injected.
     });
   }; // Close window.N.loader


   function unload(f) {
     console.log( delete window[f] ); // => true
   }

   window.N.loader();

 } catch (err) {
   console.log(err);
 } finally {
 }

是的,它可以 - 需要注意的是。您实际上并没有删除该对象。相反,您只是删除内存中 window 属性 和对象之间的 link

当你delete时,属性处的对象仍然存在。如果没有其他东西引用它,它通常会在几秒钟内被垃圾回收。如果其他东西仍然引用它,除非其他东西发生变化,否则它永远不会被垃圾收集。

举个简单的例子:

(() => {
  const theNamespace = {
    fn() {
      delete window.propertyA;
    }
  };
  window.propertyA = theNamespace;
  window.propertyB = theNamespace;
})();
window.propertyA.fn();
console.log(window.propertyB);

or only making them unreachable from the remaining JS code

是的,只要某个对象引用了同一个对象,该对象就会保留(大部分 - 参见 mark and sweep)。如果您删除 window.N,对 window.n 的其他引用将停止工作 - 但如果其他内容在其他 属性 或标识符中引用了同一对象,这些引用将继续工作。