在JavaScript中删除对象


359

我对JavaScript的delete运算符有些困惑。采取以下代码:

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

var foo = obj;

delete obj;

执行完这段代码后,objis null,但foo仍指的是一个完全像的对象obj。我猜这个对象是foo指向相同的对象。

这使我感到困惑,因为我希望编写会delete obj删除obj指向内存中的对象,而不仅仅是变量obj

这是因为JavaScript的垃圾回收工作在保留/释放的基础,所以,如果我没有指向对象的任何其他变量,它从内存中清除?

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





1
@Steve Harrison删除不是用于在javascript中删除对象的操作,用于在您var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;未删除对象的情况下删除对象键的操作,请检查obj删除用法:delete obj.helloText然后检查foo now foo is an empty object
Umair Ahmed

2
@UmairAhmed,免费翻译:“”“ delete不是用于删除javascript中delete的对象。用于删除对象密钥。在您的情况下var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;,该对象没有被删除。检查obj。接下来,运行delete obj.helloText,您foo现在可以看到指向空object。“”“
Pacerier

Answers:


448

delete运算符仅删除引用,而不删除对象本身。如果确实删除了对象本身,则其他剩余的引用将像C ++删除一样悬而未决。(访问其中之一将导致崩溃。将它们全部变为null意味着删除时需要额外的工作或为每个对象分配额外的内存。)

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

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


23
delete关键字只适用于一个对象的属性,而不是变量。perfectionkills.com/understanding-delete
Alex Mund

1
@AlexJM是的,Guffa的下一个答案(及其评论)对此进行了详细讨论。
Jesse Rusak 2015年

1
对象的属性可以是另一个对象。例如; var obj = {a: {}}; delete obj.a;
Alex Mund 2015年

2
但是...变量实际上不是的属性window吗?
RedClover

3
@Soaku不是局部变量。(例如声明为的声明var
Jesse Rusak '17

162

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中测试。)


39
如果在全局范围内执行此操作,则您的x变量将仅成为全局window对象的属性,并且delete x;确实会x完全删除该变量。
Crescent Fresh

18
@crescentfresh:仅是隐式声明的属性。如果在示例中明确声明,则它是全局变量,不能删除。
Guffa

4
@Tarynn:我知道,这就是问题所在。如果在控制台中执行此操作,则由于某些原因,x在某些浏览器中不是适当的变量,而是window对象中的属性。这当然是控制台的问题,并且不能反映代码的正常执行方式。
Guffa

2
@Guffa经过一堆研究后,我不得不承认这可能是一件好事,因为我没有足够的反对票。致以诚挚的歉意,并感谢您抽出宝贵的时间向我展示发生了什么事情……这里是一个深入的探讨:perfectionkills.com/understanding-delete/#firebug_confusion
Tarynn 2013年

2
@chao:我知道了。您遇到的问题与Tarynn相同(请参阅前面的评论)。当您在控制台中执行此操作时,它的功能与实际代码中的功能不同。
Guffa

56

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


53
我从来没有意识到var太糟糕了。
加文2014年

1
这是一个好点,是JS的陷阱。人们习惯于删除窗口变量,然后想知道为什么他们不能对局部变量做同样的事情。
welbornio

2
同样适用let
Pacerier's


4

delete 不用于删除Java脚本中的对象。

delete用于删除object key您的案例

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

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

delete obj.helloText

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


2

刚发现一个jsperf,鉴于此,您可能会觉得有趣。(将其保留以完成图片可能很方便)

它比较delete,设置null和设置undefined的情况

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



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

1

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


1

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

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

什么是最佳做法?我记得读过删除操作符并不是删除对象属性的最佳方法。我相信我在Crockford的JavaScript书中读了此书,但目前无法对其进行深入研究。
zero_cool

0

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.