2

Im wondering how to properly "Clear" a object instance. With the code below, the internal setInterval() will continue to run even after the instance is "cleared" by the parent.

// 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 );

Output:

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

Problem is that the "aClass tick" message continues to print after the test().

Ideas?

4
  • 3
    setInterval and its handler has nothing to do with your object. Commented Jan 20, 2013 at 0:32
  • 3
    @VisioN - the OP's point is that if a reference to the object is maintained in a closure, the object isn't ever really "deleted". Commented Jan 20, 2013 at 0:34
  • The object is deleted, inst is null in the second console log. The function tick is copied when used as a parameter to setInterval. Commented Jan 20, 2013 at 3:07
  • Possible duplicate of Stop setInterval call in JavaScript Commented Dec 25, 2015 at 22:52

4 Answers 4

3

Your instance is being kept in memory because the function you passed to setInterval is being kept in memory and has a reference to it. That function is referenced by the browser's list of active interval timers.

You'll need to remember the interval handle:

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

...then later when you're dropping your reference to inst, you'll want to tell it that:

inst.cleanup();
inst = null;

...and in inst.cleanup:

clearInterval(this.intervalHandle);

That way, the browser will remove its reference to the function you passed to setInterval, which means that function will become eligible for garbage collection (based on your code there are no other references to it). And that means the reference it has to your instance is released, and so if no other outstanding references to that instance exist, it's eligible for garbage collection.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for super explanation. This is exactly what I feared. Is there really no way to "force-delete" it?
@jorgenskogmo: No, the nature of garbage-collected environments is that the only way to "delete" something is to ensure there are no outstanding references to it and let the GC do its thing. In this case, that's pretty easy, though, as described. If you could force it, that would just introduce new problems (errors caused by things referencing something that you "forced" out of memory).
2

You should use clearInterval() rather than try to delete the reference. This has been answered before - see Stop setInterval call in JavaScript

Comments

0

That's because the browser itself keeps track of all the functions scheduled with setInterval and setTimeout. (Otherwise you'd have to store the function yourself somewhere, which in most cases would be pretty annoying.) And your function has a reference to a method, so that method stays alive. But I suspect the rest of the object would have been thrown away, though that's a bit difficult to prove.

If you ever plan to unschedule such a function, you need to do so explicitly:

this.interval = setInterval(function, 4000);

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

And, by the way, you should very rarely need to return a big hash like that from a constructor! Work with the prototype instead:

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

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

2 Comments

Regarding the "store a ref to the setInterval()" - Yes. Thanks. About the prototype vs constructor > return {}, this seems to be about coding "style" or habit - or is there really a reason to one instead of the other?
most habits exist for a reason: in this case, you're creating a new copy of the entire class every time you create an object.
0

My guess is that your instance of aClass is gone since there is no way to access any of it's properties but in init the tick function is copied when used as a parameter to 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);

To illustrate that the function is copied:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.