2013-01-20 56 views
2

我想知道如何正确“清除”一个对象实例。 使用下面的代码,内部setInterval()即使在父实例被“清除”之后仍将继续运行。如何在javascript中删除/清除/忘记对象实例?

// simple Class 
var aClass = function(){ 
    return { 
     init: function(){ 
      console.log("aClass init()") 
      setInterval(this.tick, 1000); 
      // note: we're not storing the ref 
     }, 
     tick: function(){ 
      console.log("aClass tick"); 
     } 
    } 
} 

// instantiate the class 
var inst = new aClass(); 
inst.init(); 


// try to forget the instance 
function test(){ 
    console.log("test() 1 inst:", inst); 

    inst = null; 

    console.log("test() 2 inst:", inst); 
} 

// run for a while, then call test() 
setTimeout(test, 4000); 

输出:

aClass init() 
aClass tick 
aClass tick 
aClass tick 
test() 1 inst: {.....} 
test() 2 inst: null 
aClass tick 
aClass tick ... 

问题是, “ACLASS嘀” 消息继续试验后打印()。

想法?

+3

'setInterval'及其处理程序无关,与你的对象。 – VisioN

+3

@VisioN - OP的观点是,如果对象的引用保持在闭包中,则该对象不会真的被“删除”。 – nrabinowitz

+0

该对象被删除,inst在第二个控制台日志中为空。当用作setInterval的参数时,函数节点被复制。 – HMR

回答

3

您的实例将被保存在内存中,因为你传递给setInterval功能被保存在内存中,并具有对它的引用。该功能由浏览器的活动间隔定时器列表引用。

你需要记住的间隔手柄:

this.intervalHandle = setInterval(this.tick, 1000); 

......再后来,当你下降到inst你参考,你要告诉它:

inst.cleanup(); 
inst = null; 

...在inst.cleanup

clearInterval(this.intervalHandle); 

这样的话,浏览器会雷莫请参考您传递给setInterval的函数,这意味着函数将符合垃圾回收的条件(根据您的代码,没有其他引用)。这意味着参考文献必须将您的实例发布,因此如果没有其他未完成的对该实例的引用存在,则它符合垃圾回收的条件。

+0

感谢您的超级解释。这正是我所担心的。真的没有办法“强制删除”它吗? – jorgenskogmo

+1

@jorgenskogmo:不,垃圾收集环境的本质是,“删除”东西的唯一方法是确保没有未完成的引用,并让GC完成它的工作。在这种情况下,如上所述,这很容易。如果你能*强制它,那只会引入新的问题(由于引用了某些你“被迫”出内存的东西而引起的错误)。 –

0

这是因为浏览器本身保持跟踪setIntervalsetTimeout计划的所有功能。 (否则,你不得不在某处存储函数,在大多数情况下这会非常恼人)。而且你的函数有一个方法的引用,所以这个方法仍然存在。但我怀疑其余的东西会被扔掉,尽管这有点难以证明。

如果你打算取消预定这样的功能,你需要明确这样做:

this.interval = setInterval(function, 4000); 

// and then later, in some `destroy()` method 
clearInterval(this.interval); 

而且,顺便说一句,你应该很少需要从构造函数返回一个大哈希那样的!与原型工作,而不是:

var SomeClass = function() { 
    // ... 
}; 

SomeClass.prototype.method = function() { 
    console.log('hello from', this); 
}; 
+0

关于“将参数存储到setInterval()” - 是的。谢谢。关于原型vs构造函数> return {},这似乎是关于编码“样式”或习惯 - 还是真的有一个理由而不是另一个呢? – jorgenskogmo

+0

大多数习惯存在的原因是:在这种情况下,每次创建对象时都要创建_entire class_的新副本。 – Eevee

0

我的猜测是,你ACLASS的情况已经一去不复返了,因为没有办法访问任何它的性能,但在初始化作为一个参数给setInterval使用时刻度功能被复制。

var tickfunction=null; 
var aClass = function(){ 
    return { 
     init: function(){ 
      console.log("aClass init()") 
      tickfunction = this.tick; 
     }, 
     tick: function(){ 
      console.log("aClass tick"); 
     } 
    } 
} 

// instantiate the class 
var inst = new aClass(); 
inst.init(); 

// try to forget the instance 
console.log("test() 1 inst:", inst); 
inst = null; 
console.log("test() 2 inst:", inst);// its null isn't it? 
console.log("the tickfunction:",tickfunction); 

为了说明该功能被复制:

function toInterval(){ 
    console.log("orig"); 
} 
setInterval(toInterval,1000);//prints orig every second 
toInterval=function(){ 
    console.log("changed it"); 
} 
toInterval();//prints changed it