在JavaScript中删除对象

时间:2009-04-12 23:18:32

标签: javascript pointers object memory-management garbage-collection

我对JavaScript的delete运算符感到困惑。请使用以下代码:

var obj = {
    helloText: "Hello World!"
};

var foo = obj;

delete obj;

执行完这段代码后,objnull,但foo仍然引用与obj完全相同的对象。我猜这个对象与foo指向的对象相同。

这让我感到困惑,因为我期望写delete obj删除obj在内存中指向的对象 - 而不仅仅是变量obj

这是因为JavaScript的垃圾收集器正在保留/释放,所以如果我没有指向该对象的任何其他变量,从内存中删除吗?

(顺便说一句,我的测试是在Safari 4中完成的。)

12 个答案:

答案 0 :(得分:434)

删除操作符仅删除引用,而不删除对象本身。如果它确实删除了对象本身,那么其他剩余的引用将是悬空的,就像C ++删除一样。 (并且访问其中一个会导致崩溃。要使它们全部转为null将意味着在删除或为每个对象额外的内存时有额外的工作。)

由于Javascript是垃圾收集的,因此您无需自行删除对象 - 当无法再引用它们时,它们将被删除。

如果您已完成对象的删除,则删除对象的引用会很有用,因为这会为垃圾回收器提供有关可以回收的内容的更多信息。如果对大对象的引用仍然存在,这可能导致它无法回收 - 即使程序的其余部分实际上没有使用该对象。

答案 1 :(得分:155)

delete命令对常规变量没有影响,只影响属性。在delete命令后,该属性没有值null,它根本不存在。

如果属性是对象引用,则delete命令将删除属性,但不删除对象。如果对象没有其他引用,则垃圾收集器将处理该对象。

示例:

var x = new Object();
x.y = 42;

alert(x.y); // shows '42'

delete x; // no effect
alert(x.y); // still shows '42'

delete x.y; // deletes the property
alert(x.y); // shows 'undefined'

(在Firefox中测试过。)

答案 2 :(得分:54)

“隐式声明的变量”是全局对象的属性,因此delete对它们起作用就像它适用于任何属性一样。用var声明的变量是坚不可摧的。

答案 3 :(得分:23)

来自Mozilla文档,“您可以使用delete运算符删除隐式声明的变量,但不能删除使用var语句声明的变量。”

以下是链接:https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Operators:Special_Operators:delete_Operator

答案 4 :(得分:6)

基于@Guffa的回答。我发现以下方法对我有用:

var obj = {
    helloText: "Hello World!"
};

obj = null;

delete obj;

首先将obj设置为null,删除了对它的所有引用,然后就可以完全删除它。

我没有在其他浏览器上测试它,但这适用于phonegap 1.7.0

答案 5 :(得分:4)

delete不用于删除java Script中的对象。

delete用于删除案例中的object key

var obj = { helloText: "Hello World!" }; 
var foo = obj;
delete obj;

对象未删除检查obj仍然采用相同的值删除用法:

delete obj.helloText

然后检查obj, foo,两者都是空对象。

答案 6 :(得分:2)

除了GC问题,对于性能,我们应该考虑浏览器可能在后台进行的优化 - >

http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/

似乎取消引用可能比删除它更好,因为这可能会改变Chrome使用的幕后“类”。

答案 7 :(得分:2)

根据此事,您可能会认为有趣的jsperf。 (保持它完成图片可能很方便)

比较删除,设置 null 并设置未定义

但请记住,当你多次删除/设置属性时,它会测试这种情况。

答案 8 :(得分:1)

IE 5到8有一个错误,即在主机对象(Window,Global,DOM等)的属性上使用delete会引发TypeError“对象不支持此操作”。

var el=document.getElementById("anElementId");
el.foo = {bar:"baz"};
try{
    delete el.foo;
}catch(){
    //alert("Curses, drats and double double damn!");
    el.foo=undefined; // a work around
}

稍后,如果您需要检查属性具有完全值的含义,请使用el.foo !== undefined,因为"foo" in el 将永远在IE中返回true。

如果你真的需要财产真的消失......

function hostProxy(host){
    if(host===null || host===undefined) return host;
    if(!"_hostProxy" in host){
       host._hostproxy={_host:host,prototype:host};
    }
    return host._hostproxy;
}
var el=hostProxy(document.getElementById("anElementId"));
el.foo = {bar:"baz"};

delete el.foo; // removing property if a non-host object

如果您需要将主机对象与主机API一起使用...

el.parent.removeChild(el._host);

答案 9 :(得分:0)

我在寻找同样的答案时偶然发现了这篇文章。我最终做的只是弹出obj.pop()我对象中所有存储的值/对象,以便我可以重用该对象。不确定这是不好的做法。这种技术对我在Chrome Dev工具或FireFox Web控制台中测试代码非常方便。

答案 10 :(得分:0)

将变量设置为null可确保破坏对所有浏览器中对象的任何引用,包括在DOM元素和Javascript范围之间进行循环引用。通过使用delete命令,我们在下一次运行Garbage集合时标记要清除的对象,但是如果有多个变量引用同一个对象,则删除单个变量将不会释放该对象,它只会删除该变量与对象之间的联系。在下一次运行垃圾收集时,只会清除变量。

答案 11 :(得分:0)

这项工作对我来说虽然不是一个好习惯。它只是删除所有 对象所属的关联元素。

 for (element in homeService) {
          delete homeService[element];