我正在忙着学习使用对象的原型继承。我的代码目前正常运行。但我现在要做的是避免造成内存泄漏。
我有一堆在父对象中调用的HTML选择器。这些稍后用于删除和添加一些CSS动画。
我现在想要做的是基本上删除或使父构造函数变为未定义,并让其子代没有对这些选择器的引用。
这是一个Code Share因为我不想在这里全部转储它。但问题是父母是:
var GameStartup = function() {
this.welcomeStartBtn = document.querySelector('.game-startup__welcome a');
this.welcomeStartBtn__controller = document.querySelector('.game-startup__welcome a span:first-child');
this.welcomeStartBtn__copy = document.querySelector('.game-startup__welcome a span:last-child');
};
所以基本上我想要它的子ShowLogin和父类是未定义的,或者它不能再创建像detatched dom节点等东西。
答案 0 :(得分:1)
你可以做的一件事是使用这样的getter:
function GameSartup () {}
GameSartup.prototype = {
constructor: GameSartup,
get welcomeStartBtn () {
return document.querySelector('.game-startup__welcome a');
}
// more getters here
}
这样你可能会有一些开销,因为你每次“获取”DOM元素时都会查询dom,但是你会删除所有引用。
如果这样做太慢,你可以为元素引用创建一个缓存,如下所示:
function GameSartup () {
this.domcache = {};
}
GameSartup.prototype = {
constructor: GameSartup,
get welcomeStartBtn () {
var selector = '.game-startup__welcome a';
if (!this.domcache.hasOwnProperty(selector)) {
this.domcache[selector] = document.querySelector(selector);
}
return this.domcache[selector];
},
// more getters here
trash: function () {
this.domcache = null;
delete this.domcache;
}
}
这样您可以立即释放所有引用,但仍需手动清除缓存。但是如果你创建一个GameSartup
对象,那么:
var gs = new GameSartup();
以后:
gs = null;
并且不存在对gs
的其他引用,垃圾收集器将发现也没有对domcache
的引用并删除它。
<强>更新强>
回应评论:
»缓存失效«始终是应用程序中的关键点,缓存本身可能会变得复杂并导致奇怪的错误。但它也可以真正加快速度。这取决于应用程序应该/必须有多复杂。
在这种情况下,我会在没有缓存的情况下开始,如果性能良好,那么你就完成了。
我认为下一步可能如上所述:在某些事件中立即清除整个缓存。该方法可能如下所示:
//you do not need to loop over the cache and set the values to undefinded
//the garbage collector will free memory
//as soon as there is no reference to a given object left
clearCache: function(){
this.domcache = {};
return this;
}
下一步是实现»每项缓存«如:
addToCache: function (key, value) {
if (!this.domcache.hasOwnProperty(key)) {
this.domcache[key] = value;
}
return value;
}
clearFromCache(key) {
delete this.domcache[key];
return this;
}
从缓存中清除项目,只是在添加它们之后是没用的,因为这只是没有缓存加上管理它的开销。
总而言之,它取决于一系列因素,如:
如果有疑问,你应该做一些有或没有缓存的基准测试,以找到有效的带走。
更新#2
由于你在谈论DOM元素 - 只要一个元素是DOM的一部分(有一个父节点) - 它就不会被垃圾收集器删除,因为它有对它的引用(childNodes数组中的项目)。 / p>
因此,如果您害怕由于运行时创建的元素太多而导致的内存泄漏:
var elements = [];
for(var i = 0; i < 10000; i++) {
var div = document.body.appendChild(document.createElement('div'));
elements.push(div);
}
比你必须做两件事:从dom中移除每个元素elements[i]
,如:
elements[i].parentNode.removeChild(elements[i]);
和
elements = null; //or a new array