如何对外部Javascript加载进行垃圾收集?

如何对外部Javascript加载进行垃圾收集?,javascript,performance,garbage-collection,dynamic-script-loading,Javascript,Performance,Garbage Collection,Dynamic Script Loading,给定一个加载器: function loader(src, callback, fail) { let s = document.head.appendChild(document.createElement('script')); s.type = "text/javascript"; s.src = src; s.onload = function() { callback() s.onload = null; //useful

给定一个加载器:

function loader(src, callback, fail) {
    let s = document.head.appendChild(document.createElement('script'));
    s.type = "text/javascript";
    s.src = src;
    s.onload = function() {
        callback()
        s.onload = null; //useful?
        s = null; //or maybe this?
    }
    s.onerror = fail
}

拥有一行
s.onload=null
是否有利于GC释放一些内存

是的,将属性设置为
null
确实对GC有利。这样做将删除元素(包含在DOM中)对处理程序函数的引用,并且假设它可能是对函数的唯一引用,则会使函数符合收集条件。然而,除非函数是保留一大块内存的变量的闭包,否则这不太可能产生很大的影响


您可能还希望从回调中的DOM中删除
s
元素,使其也可以进行垃圾收集。

是的,
s.onload=null
非常有用,并且会进行垃圾收集

。这意味着它可以在需要时收集信息。
尽管将where设置为
null
可能会更早地执行GC(但不会触发GC)

从2012年起,所有现代浏览器都提供垃圾收集器。
它的工作原理是可达性:

所有无法从全局上下文访问的对象都将被删除

当包含对象的每个变量返回、重新分配或设置为null时,标记和扫描会定期发现并删除对象。此外,现在不需要递归地将任何变量都无法访问的内容设置为null——它是通过标记和扫描来收集的

现在来看看有问题的代码

不需要
s=null
,因为变量在函数返回时会清除,闭包从调用堆栈中移除,GC负责
s

但是仍然有对scripts
onload
属性的引用,因为
是DOM中
文档的子级。head
可从
窗口访问

回调的内容可能是可访问的,但在这里是毫无疑问的

如果浏览器足够聪明,可以在内部设置
s.onload=null
,该怎么办?我们首先在第一个代码段中注释掉它,然后在第二个代码段中取消注释

函数获取(src、回调、失败){
设s=document.head.appendChild(document.createElement('script');
s、 type=“text/javascript”;
s、 src=src;
s、 onload=函数(){
回调函数()
//s、 onload=null;//有用吗?
}
s、 onerror=失败
}
取回(“https://stackoverflow.com", 
()=>{console.log(“执行onload”);},
()=>{console.log(“未找到文件”);})
设置超时(()=>{
console.log(document.head.lastChild.onload)

},1000)
在这种情况下,
s
(或
这个
)到底是什么?通常整个对象都可以被收集。
delete frag
永远不会做任何事情–
delete
删除属性。打开严格模式。另外,我很确定Bergi从未推荐过它……打开严格模式会告诉你,
delete frag
没有意义。我认为脚本也没有一个
onreadystatechange
。为什么要在脚本周围创建一个片段包装器,它不是唯一要附加的元素吗?它是一个DocumentFragment,最大限度地减少了回流,现在已从文章中删除。注:
s.onload=null
可替换为
s=null
?我编辑了我的文章,这样你就可以看到
s
的范围了。它不是重新分配
s
。对于每个
fetch
,它都是一个新的
s
。现在您可以看到并能够完善您的答案。现在我们可以更准确地说删除s了吗?不,
s=null
是没有意义的,因为
s
的作用域无论如何都不会被保留,当
fetch
函数结束时,变量会被删除(假设没有关闭)。所以我们忽略了对script元素的引用。但是为了使这些内容符合垃圾收集的条件,我们需要删除所有对这些值的引用。对脚本元素最重要的引用是它包含在DOM中——页面上的任何代码都可以通过DOM API访问脚本对象,并调用其
onload
方法。这是我们需要澄清的参考。根据您所说的,最好不要让任何
返回s
,以确保闭包不被保留且可收集。或者让返回值变为void(并使用它进行闭包)。是的,正如你所说,
s=null
是毫无意义的。也许任何试图帮助GC的ATEMT都是毫无意义的,正如我在回答中所发现的那样?@palisudarshanterho
返回s
并不重要,只要调用代码没有将值存储在某个地方。不,这与闭包无关。“
s.onload
不可访问,因为它只在脚本执行后直接调用一次”-不。正在使用和可访问彼此无关。您不想再次使用它,对吧,但是DOM仍然引用它,这就是您应该显式清除它的原因。从安全的角度来看,这是有意义的。如何清除它@Bergi:DOM仍然引用它-在哪种情况下它引用它?我希望您区分onload代码和script-code。您可以通过
s.onload=null
和/或
s.remove()
来清除它。
document.head
引用其
s
子元素,该子元素通过
.onload
属性引用处理函数。