什么时候JavaScript对象被破坏?

时间:2012-04-11 19:32:39

标签: javascript

在C ++中,我可以显式定义构造函数和析构函数,然后cout<<在构造函数/析构函数中使用“C或D调用”,以确切知道在哪里。

但是在JavaScript中如何知道对象何时被破坏。以下示例是关注我的案例。

我正在超时调用内部函数,我想知道只要计时器正在运行,对象是否保持活动状态,等待再次调用。

用户点击通话控件

// Calls  Control

控制来电消息

var message_object = new Message( response_element );

消息调用效果

new Effects().fade( this.element, 'down', 4000 );
message_object.display( 'empty' );

效果

/**
 *Effects - build out as needed
 *  element - holds the element to fade
 *  direction - determines which way to fade the element
 *  max_time - length of the fade
 */

var Effects = function(  ) 
{
    this.fade = function( element, direction, max_time ) 
    {
        element.elapsed = 0;
        clearTimeout( element.timeout_id );
        function next() 
        {
            element.elapsed += 10;
            if ( direction === 'up' )
            {
                element.style.opacity = element.elapsed / max_time;
            }
            else if ( direction === 'down' )
            {
                element.style.opacity = ( max_time - element.elapsed ) / max_time;
            }
            if ( element.elapsed <= max_time ) 
            {
                element.timeout_id = setTimeout( next, 10 );
            }
        }
        next();
    }
};

6 个答案:

答案 0 :(得分:26)

JS对象本身没有析构函数。

JavaScript对象(和原语)在不可访问时被垃圾收集,这意味着当前执行上下文中没有可能的引用。 JavaScript运行时必须持续监视此情况。因此,除非您使用delete关键字删除某些内容,否则它的破坏程度有点暴力。有些浏览器在检测闭包范围内留下的引用时很糟糕(我正在看你,Redmond)这就是为什么你经常看到在函数结束时将对象设置为null的原因 - 以确保在IE中释放内存。 / p>

答案 1 :(得分:15)

这种观念认为对象破坏可以简化为内存垃圾收集,这对我来说是危险的误导,因为问题不能简化为释放内存。

析构函数负责释放其他资源,例如文件描述符或事件侦听器,这些资源不会通过垃圾回收自动处理。在这种情况下,绝对需要析构函数在释放内存之前解除状态,否则会泄漏资源。

在这种情况下,问题是析构函数不是一流的概念,无论是需要显式调用还是在对象无法访问后都可以隐式调用。

解决这个问题的最佳方法是,如果需要使用析构函数,则要正确记录模块,并强调资源泄漏情况不能使用。

答案 2 :(得分:4)

ECMAscript中根本没有动态内存管理。垃圾收集器将处理脚本中需要内存的任何内容。实际上问题应该更像是,

  

“垃圾收集器如何知道何时可以为对象释放内存”

简单地说,大多数GC看看是否有任何有效参考。这可能是由于父上下文对象,原型链或对给定对象的任何直接访问。在您的特定实例中,只要setTimeout执行,它就会调用next()关闭.fade()父上下文,.face()函数依次保持对{ {1}}函数(上下文)。

这意味着,只要有Effects的调用,整个构造就会被保存在内存中。

你可以通过setTimeout变量来帮助老式的GC实现,通过null变量 - 对它的引用能够更早或者根本收集一些东西,但现代实现对这些东西非常聪明。实际上,您不必关心“对象/参考实时”等内容。

答案 3 :(得分:2)

我熟悉大约8种不同的通用编程语言。来自C ++环境,您会发现除C ++之外几乎没有其他语言能正确实现析构函数。 (从C ++的角度来看)第一个缺陷是破坏被认为仅与内存有关。无法执行用户定义的功能,例如关闭文件句柄或终止网络连接以作为销毁的一部分。几种语言可以让您编写自定义析构函数,但是它们还有第二个失败之处,即它们在对象超出范围时不执行析构函数。只要运行时方便,他们就会花时间。这使得它们在某些情况下不可用,例如释放多线程锁或自动关闭对话框,或者不管当前如何退出函数,都可能获取当前的微秒时间戳来测量函数执行时间。但是,您只需要意识到这一点并接受这些限制,并希望该语言的其他出色功能可以补偿您。

答案 4 :(得分:0)

有一个实验性的Firefox和Chrome功能 当浏览器空闲时回调的window.requestIdleCallback()。这可以用来模拟类实例的析构函数。

可以从以下代码获得几乎相同的效果:

setTimeout(function()
    {
    // Simulate destructor here
    },0);

这将设置一个自动解除的超时,该超时将在当前JavaScript脚本完成(并且主事件循环恢复)时完成。

答案 5 :(得分:0)

另一个重要的考虑因素是数据结构中的循环引用:“ A引用B,B引用A,并且再也没有引用它们中的任何一个。”从理论上讲,这可能会导致A和B都被视为无法回收,从而导致内存泄漏。

此处讨论了该主题,并提供了一些近期更新:

Is it possible to create a "weak reference" in javascript?

其中讨论的策略是“削弱” A和B之间的引用之一,以便垃圾收集器知道它可以被破坏,从而导致它们最终被收割……甚至可能被盗。 em>在内存不足的情况下。

当然,也可以从纪律中受益。如果您知道将不再使用某些东西,请编写一个例程,将其各种引用字段设置为 var EC = protractor.ExpectedConditions; var ele = element(by.control({controlType: "sap.m.ObjectIdentifier", id: /clone/, properties: {text: "MANAGER"}})); var isVisible = EC.visibilityOfElementLocated(ele); browser.wait(isVisible, 5000); //wait for an element to become visible browser.sleep(3000) ,然后再将其丢弃到垃圾收集器... “保持整洁。”


JavaScript自最早的实现以来,JavaScript的垃圾收集策略就变得非常重要,因为该语言已变得如此重要。在学习有关此主题的文本时,请确保它们是最近的