2

我想知道如何正确“清除”对象实例。使用下面的代码,即使在实例被父级“清除”后,内部 setInterval() 仍将继续运行。

// 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 tick”消息在 test() 之后继续打印。

想法?

4

4 回答 4

3

您的实例被保存在内存中,因为您传递给的函数setInterval被保存在内存中并且具有对它的引用。该函数被浏览器的活动间隔计时器列表引用。

您需要记住间隔句柄:

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

...然后稍后当您删除对 的引用时inst,您会想告诉它:

inst.cleanup();
inst = null;

...并在inst.cleanup

clearInterval(this.intervalHandle);

这样,浏览器将删除它对您传递给的函数的引用setInterval,这意味着该函数将有资格进行垃圾收集(根据您的代码,没有其他对它的引用)。这意味着它对您的实例的引用已被释放,因此如果不存在对该实例的其他未完成引用,则它有资格进行垃圾回收。

于 2013-01-20T00:37:30.263 回答
2

您应该使用clearInterval()而不是尝试删除引用。之前已经回答过这个问题 - 请参阅 Stop setInterval call in JavaScript

于 2013-01-20T00:35:39.143 回答
0

这是因为浏览器本身会跟踪使用setInterval和安排的所有功能setTimeout。(否则您必须自己将函数存储在某个地方,这在大多数情况下会很烦人。)并且您的函数引用了一个方法,因此该方法保持有效。但我怀疑物体的其余部分会被扔掉,尽管这有点难以证明。

如果您打算取消安排这样的功能,您需要明确地这样做:

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);
};
于 2013-01-20T00:39:50.080 回答
0

我的猜测是您的 aClass 实例已经消失,因为无法访问它的任何属性,但是在 init 中,当用作 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
于 2013-01-20T03:03:00.680 回答