在JavaScript中销毁对象及其绑定

t2a7ltrp  于 2023-04-19  发布在  Java
关注(0)|答案(2)|浏览(169)

我在JavaScript中有这样的类:

(function() {
    this.testObject = function() {
        /*options*/
        this.options = arguments[0];
    };

    /*make object*/
    testObject.prototype.make = function(){

        this.targetElement = document.getElementById('testDiv');

        this.targetElement.addEventListener('mousedown', function(e){
            ...
        });
        this.targetElement.addEventListener('mouseup', function(e){
            ...
        });
        this.targetElement.addEventListener('mousemove', function(e){
            ...
        });

    };
}());

var test; // I need this to be global
function callObject(){
    test = new testObject({...});
    test.make();
}

这个对象绑定了一些事件。示例化也在另一个函数中。这是因为我有向DOM添加新元素的情况,所以为每个新元素调用callObject()来绑定事件。
但是我觉得这里有一个性能问题,当我多次调用callObject时,它变慢了。我不知道实际上是什么问题。
那么我如何删除一个对象和它绑定的所有事件呢?

mdfafbf1

mdfafbf11#

> var test; // I need this to be global
> function callObject(){
>     test = new testObject({...});
>     test.make();
> }

在上面的例子中,test 只会引用 testObject 的最后一个示例。
你使用的模式意味着prototype链上的每个函数都有一个外部IIFE执行上下文的闭包,每个由 make 方法添加的监听器也是如此。如果你不需要闭包,那么这是低效的。如果不需要,那么在这里使用IIFE是不合适的,考虑使用标准方法(惯例是给予构造函数一个以大写字母开头的名字):

function TestObject() {
    /*options*/
    this.options = arguments[0];
}

TestObject.prototype.make = function (){
    this.targetElement = document.getElementById('testDiv');
    this.targetElement.addEventListener('mousedown', function (e){
        ...
    };
    this.targetElement.addEventListener('mouseup', function (e){
        ...
    };
    ...
};

正如在其他地方提到的,使用函数表达式添加侦听器会使以后很难删除它们。上述模式也意味着每个示例都有自己的函数副本。解决这两个问题的替代方案是使用引用。您可以将它们作为构造函数的属性添加,这样它们就不会创建额外的全局变量,也不需要另一个对象,例如。

TestObject.mousedown = function (e){ ... };
TestObject.mouseup   = function (e){ ... };

TestObject.prototype.make = function(){
    var TO = TestObject;
    this.targetElement = document.getElementById('testDiv');
    this.targetElement.addEventListener('mousedown', TO.mousedown, false);
    this.targetElement.addEventListener('mouseup',  TO.mouseup, false);
    ...
};

这避免了大量的闭包和不必要的函数副本,意味着监听器可以按名称删除。你可能想让 test 成为一个对象或数组,这样你就可以保留对 TestObject 的所有示例的引用,而不仅仅是最后一个。

yqkkidmi

yqkkidmi2#

有几件事需要考虑。首先,也是最重要的,你的事件监听器有匿名函数。当你给予它一个匿名函数时,你不能解除绑定一个监听器。所以继续为这些监听器创建实际的函数。然后你可以像调用addEvent...一样调用removeEventListener,它会分离这些监听器。
我通常做的是创建一个destroy函数,删除所有侦听器并将所有全局变量设置为null。然后您可以在需要时调用该destroy函数。

相关问题