如何对外部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
但是仍然有对scriptsonload
属性的引用,因为
是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
属性引用处理函数。