如何在javascript中删除/清除/忘记对象实例?

如何在javascript中删除/清除/忘记对象实例?,javascript,object,Javascript,Object,我想知道如何正确地“清除”一个对象实例。 使用下面的代码,内部setInterval()将继续运行,即使在父实例“清除”后也是如此 // simple Class var aClass = function(){ return { init: function(){ console.log("aClass init()") setInterval( this.tick, 1000 ); // note

我想知道如何正确地“清除”一个对象实例。 使用下面的代码,内部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”消息在测试()后继续打印


想法?

您应该使用
clearInterval()
,而不是尝试删除引用。 这一点以前已经得到了回答-请参阅
您的实例被保存在内存中,因为传递给
setInterval
的函数被保存在内存中,并且有对它的引用。该函数由浏览器的活动间隔计时器列表引用

您需要记住间隔句柄:

this.intervalHandle = setInterval( this.tick, 1000 );
…然后,当您删除对
inst
的引用时,您会想告诉它:

inst.cleanup();
inst = null;
…并在
安装清理中

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

这是因为浏览器本身跟踪使用
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);
};

我猜您的aClass实例已经不存在了,因为无法访问它的任何属性,但是在init中,tick函数在用作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

setInterval
及其处理程序与您的对象无关。@VisioN-OP的要点是,如果在闭包中维护对对象的引用,则该对象从未真正“删除”。该对象被删除,inst在第二个控制台日志中为空。当用作setInterval的参数时,会复制函数tick。感谢您的解释,可能会复制函数tick。这正是我所担心的。真的没有办法“强制删除”它吗?@jorgenskogmo:不,垃圾收集环境的本质是“删除”某些内容的唯一方法是确保没有未完成的引用,并让GC完成它的工作。在这种情况下,这很容易,但是,正如所描述的。如果您可以强制执行,那只会引入新的问题(由于引用您“强制”出内存的内容而导致的错误)。关于“存储对setInterval()的引用”-是。谢谢关于prototype vs constructor>return{},这似乎是关于编码“样式”或习惯——或者说这两者之间真的有原因吗?大多数习惯的存在都有一个原因:在这种情况下,每次创建对象时都要创建整个类的新副本。