首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >垃圾收集器:删除对另一个对象的引用

问垃圾收集器:删除对另一个对象的引用
EN

Stack Overflow用户
提问于 2012-10-17 17:48:09
回答 1查看 179关注 0票数 2

据我所知,JS垃圾收集器删除了不再引用的对象。假设我删除了对一个对象的引用,该对象有一个属性,该属性是对另一个对象的引用。这两个对象都将被删除吗?

e.g

代码语言:javascript
复制
var objectA = {
    prop1: "property",
    prop2: "property"
}

var objectB = {
    refToA: objectA
}

// Remove reference to objectA
delete objectA;

// Remove reference to objectB
delete objectB

这两个对象现在都从内存中完全删除了吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-10-17 17:54:03

简短的回答是:是的。未在任何地方引用的对象将从内存中完全删除,而不管该对象属性引用的是什么。

在您的代码片段中,事情相当简单,尽管当您开始使用闭包时,mem管理可能会变得棘手:

代码语言:javascript
复制
var objA = (function()
{
    var objAb = {who:'An object literal in closure scope',globalReference:'None!'};
    return {who:'Return value, is an object literal that references a closure object'.
            closureObj : objAb};
})();
var objB = {who:'some object',objAb:{who:'object literal, referenced by objB.objAb'}};
var objBAb = objB.objAb;//reference to obj literal, referenced by objB.objAb
var objAb = objA.closureObj;//reference to obj literal, referenced by objA.closureObj, which in turn references the closure object literal

delete objB.objAb;
console.log(objBAb);//<-- the object literal that was declared as a property of objB still exists
delete objAb;//<-- this reference is gone, but the closure obj still exists 
console.log(objA.closureObj);//<-- object is there

基本上,对象是无名称的实体。用于访问它们的变量是引用,永远不会包含实际的对象本身。它漂浮在JS-space中。当您使用delete someVar时,您所要做的就是取消设置该变量的实际值,这是一个内存地址(某种意义上)。

如果JS找不到任何引用内存中包含对象的位置的变量,它将回收该内存。

事情就是这么简单。

当您将此逻辑应用于以下代码时:

代码语言:javascript
复制
var objA = (function()
{
    var closureObj = {iam:'An object literal defined inside a closure scope'};
    var functionsAreObjects = function()
    {//nameless function object, inside closure scope, too
        return closureObj;
    };
    var resetFunction = function()
    {
        this.closureReference = functionsAreObjects();//assign return value to this
    };
    return {iam:'The returned object literal',
            closureReference:closureObj,
            reset:resetFunction,
            getClosureReference:functionsAreObjects};
})();
delete objA.closureReference;//the closure object IS NOT GC'ed

在前面的示例中,最后一条delete语句足以GC闭包对象文字。但是,现在objA有两个方法(引用函数对象的属性)。这些方法仍然引用closure对象,并且仍然被objA引用,所以closureObj还不能被GC‘。所以,这就是事情变得棘手的地方:

代码语言:javascript
复制
delete objA.closureReference;
delete objA.reset;
delete objA.getClosureReference;

我们已经删除了所有可以链接回closureObj的属性,因此理所当然地它将被GC,对吧?--呃,不完全是。Chrome的V8确实会释放内存,但我听说过类似的代码导致了Opera的泄漏,而且IE可能不会在回收内存方面出类拔萃。

此外,我们已经使用getClosureReference有效地创建了一个getter方法,因此在现实生活中,这很可能发生:

代码语言:javascript
复制
//do stuff
delete objA.closureReference;
var objB = objA.getClosureReference();//<-- created new reference to closure object
//do some more stuff
delete objA.reset;
delete objA.getClosureReference;

在这种情况下,无法对closureObj进行GC处理,因为objB仍在某处引用它。只有当该变量超出作用域时,closureObj才会被释放。这不仅是反对全局变量的一个非常可靠的论据(它们从不超出作用域,因此也不会被GC‘’ed),它还表明了闭包,尽管它们很整洁,但需要开发人员更多的开销:让变量超出作用域并不一定意味着内存被释放:一些闭包可能会公开对对象的引用,或者引用该对象的函数……

我已经在a while ago上发布了一个关于这个问题的问题,但它可能解释了一些事情。

有趣的是,如果您想要一个嵌套闭包的示例(闭包中的闭包、闭包中的闭包、相互传递引用以及其他对象),try finding out when what can be GC'ed in the following code

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12931543

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档