在 javascript 中销毁对象及其绑定
Destroy objects and their bindings in javascript
我在 javascript
中有这个 class
(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
时速度变慢了。我不知道实际上是什么问题。
那么如何删除对象及其所有绑定事件?
有几件事需要考虑。首先,也是最重要的,您的事件侦听器具有匿名函数。当你给它一个匿名函数时,你不能解除绑定一个监听器。因此,继续为这些功能制作实际功能。然后你可以像调用 addEvent...
一样调用 removeEventListener
,它会分离那些监听器。
我通常做的是制作一个 destroy
函数,该函数删除所有侦听器并将任何全局变量设置为 null
。然后你可以在任何需要的时候调用那个 destroy 函数。
> var test; // I need this to be global
> function callObject(){
> test = new testObject({...});
> test.make();
> }
在上面,test 只会引用 testObject 的最后一个实例。
您使用的模式意味着原型链上的每个函数都有一个到外部 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 所有实例的引用,而不仅仅是最后一个实例。
我在 javascript
中有这个 class(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
时速度变慢了。我不知道实际上是什么问题。
那么如何删除对象及其所有绑定事件?
有几件事需要考虑。首先,也是最重要的,您的事件侦听器具有匿名函数。当你给它一个匿名函数时,你不能解除绑定一个监听器。因此,继续为这些功能制作实际功能。然后你可以像调用 addEvent...
一样调用 removeEventListener
,它会分离那些监听器。
我通常做的是制作一个 destroy
函数,该函数删除所有侦听器并将任何全局变量设置为 null
。然后你可以在任何需要的时候调用那个 destroy 函数。
> var test; // I need this to be global
> function callObject(){
> test = new testObject({...});
> test.make();
> }
在上面,test 只会引用 testObject 的最后一个实例。
您使用的模式意味着原型链上的每个函数都有一个到外部 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 所有实例的引用,而不仅仅是最后一个实例。