根据mdn documentation,方法removeChild
从DOM中删除了一个节点,但它仍然驻留在内存中。我的问题是我也想从内存中删除它。我试过delete
运算符,但对象仍在那里......
myCanvas.parentElement.removeChild(myCanvas); // myCanvas actually removed from DOM
delete myCanvas; // false. does nothing
alert(myCanvas); // shows HTMLCanvasElement instead of undefined
阅读http://perfectionkills.com/understanding-delete/。删除操作符不适用于变量(这就是它返回false
的原因)。
如果要删除变量对DOM节点的引用,请使用
myCanvas = null;
覆盖该值。通常你永远不需要这样做,因为JS的垃圾收集器为你做了所有工作。
只需为myCanvas
变量(如null
)指定另一个值,这样就不会有更多变量引用canvas元素。垃圾收集将完成剩下的工作。
当然,没有保证。这假设没有其他变量引用该元素。否则,如果还有其他变量,对象等仍然引用该canvas元素,那么它根本不会从内存中删除。如果存在包含对元素的引用但无法解除引用的闭包,则会更难删除。
好吧,如果您在没有myCanvas
关键字的情况下初始化var
变量,那么您的代码片段就可以工作了,因为这些变量会自动变为configurable: true
,因此可以与delete
运算符一起处理而不会有任何麻烦。
或者,你可以使用getElementsByClassName()
method的对象引用而不是单独的HTMLElement
本身
- 我在这里假设myCanvas
是getElementById()
手术之类的结果 -
因为HTMLCollection
生成的getElementsByClassName()
将自动更新并在从树中删除后立即删除对DOM对象的任何引用。
换句话说,它本质上是活的,因此它不需要任何手动操作来破坏/清除引用。
基本答案是引用画布的所有变量都需要设置为undefined
,以便垃圾收集器可以完成其工作。但有时它在实践中并不那么简单。
在尝试完全删除动态创建的HTML canvas元素以避免内存泄漏时,我遇到了几个棘手的情况:
(1)我添加到canvas元素的方法保存了它们自己的引用(创建一个循环)。我通过在删除画布时删除所有自定义属性来解决此问题:
function deleteAllProperties(obj) {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
delete obj[key];
}
}
}
deleteAllProperties(myCanvas);
myCanvas = undefined;
(2)其他对象中的内部变量仍然引用了画布。通过将它们全部设置为undefined
来修复:
_myVar = myBuilder = myObserver = undefined;
(3)一个变量引用了画布的上下文:var ctx = myCanvas.getContext('2d');
这在某些浏览器中保存在画布上(甚至在设置了myCanvas = undefined
之后)。通过清除该变量来修复:
ctx = undefined;