简体   繁体   English

如何垃圾收集外部 Javascript 负载?

[英]How to Garbage Collect an external Javascript load?

Given a loader:给定一个装载机:

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
}

Does having a line s.onload = null benefit from GC free some memory?有一行s.onload = null是否可以从 GC 释放一些内存中受益?

Yes, s.onload = null is useful and will garbage collect!是的, s.onload = null很有用并且会被垃圾收集!

As of 2019, it is not possible to explicitly or programmatically trigger garbage collection in JavaScript . 截至 2019 年,无法在 JavaScript 中显式或以编程方式触发垃圾收集 That means it collects when it wants.这意味着它会在需要时收集。
Although there is cases where setting to null may do a GC earlier (but not trigg it to do).尽管在某些情况下设置为null可能会更早执行 GC(但不会触发它执行)。

As of 2012, all modern browsers ship a mark-and-sweep garbage-collector.截至 2012 年,所有现代浏览器都提供了标记和清除垃圾收集器。
It works from a principle of reachibility :它的工作原理是可达性

Every object not reachable from the global context is deleted删除全局上下文中无法访问的每个对象

Periodically the mark-and-sweep discover and deletes an object when every variable that holded it is returned, reassigned or set to null .当每个包含它的变量被返回、重新分配或设置为 null时,标记和清除会定期发现并删除一个对象。 Also it is nowadays not needed to recursively set null on content that is not reachable from any variable - it is collected anyway by the mark-and-sweep .此外,现在不需要对无法从任何变量访问的内容递归设置 null - 它无论如何都由mark-and-sweep收集。

Now to the code in question ...现在到有问题的代码......

The s = null is not needed, because the variable cleares anyway when function returns, closure is removed from the call-stack and GC takes care of s .不需要s = null ,因为该变量在函数返回时无论如何都会清除,从调用堆栈中删除闭包并且 GC 会处理s

but there still is a reference to the scripts onload property, as the <script onload> is a child of the document.head in the DOM reachable from the window !但是仍然有对脚本onload属性的引用,因为<script onload>是可从window访问的 DOM 中document.head的子项!

Content of the callback may be reachable, but is out of question here. callback内容可能是可达的,但在这里是不可能的。

What if browsers is smart enough to set s.onload = null internally?如果浏览器足够聪明,可以在内部设置s.onload = null呢? We try it out by first comment it away in the first snippet and uncomment it in the second snippet ...我们通过首先在第一个片段中注释掉它并在第二个片段中取消注释来尝试它......

 function fetch(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.onerror = fail } fetch("https://stackoverflow.com", () => {console.log("Execute onload");}, () => {console.log("File not found");}) setTimeout(() => { console.log(document.head.lastChild.onload) },1000)

The found file is executed with error, because it is not Javascript.找到的文件执行时出错,因为它不是 Javascript。
The onload is executed but not removed. onload被执行,但不会被移除。 The code show up in the log!代码显示在日志中!
That proves the line with s.onload = null should be used , like this:这证明应该使用s.onload = null的行,如下所示:

 function fetch(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.onerror = fail } fetch("https://stackoverflow.com", () => {console.log("Execute onload");}, () => {console.log("File not found");}) setTimeout(() => { console.log(document.head.lastChild.onload) },1000)

Yes, it does benefit the GC to set the properties to null .是的,将属性设置为null确实有利于 GC。 Doing so removes the references from the element (that is contained in the DOM) to the handler function, and given that it probably is the only reference to the function it makes the function eligible for collection.这样做会删除从元素(包含在 DOM 中)到处理程序函数的引用,并且鉴于它可能是对该函数的唯一引用,它使该函数有资格进行收集。 However, unless the function is a closure over variables retaining a large block of memory, this is very unlikely to have a lot of impact.但是,除非函数是对保留大内存块的变量的闭包,否则这不太可能产生很大影响。

You might also want to remove the s element from the DOM in the callback, making it garbage-collectable as well.您可能还想在回调中从 DOM 中删除s元素,使其也可垃圾收集。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM