Javascript:在原型继承中删除对HTML选择器的引用?

时间:2016-10-31 06:57:05

标签: javascript html

我正在忙着学习使用对象的原型继承。我的代码目前正常运行。但我现在要做的是避免造成内存泄漏。

我有一堆在父对象中调用的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节点等东西。

1 个答案:

答案 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;
}

从缓存中清除项目,只是在添加它们之后是没用的,因为这只是没有缓存加上管理它的开销。

总而言之,它取决于一系列因素,如:

  • 您需要多久查询一个元素,
  • 该元素将始终驻留在dom中,因此可以始终从dom
  • 查询它
  • 需要缓存多少元素,
  • 正确缓存这些元素需要多少代码,
  • dom中有多少元素

如果有疑问,你应该做一些有或没有缓存的基准测试,以找到有效的带走。

更新#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