369

I'm a bit confused with JavaScript's delete operator. Take the following piece of code:

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

var foo = obj;

delete obj;

After this piece of code has been executed, obj is null, but foo still refers to an object exactly like obj. I'm guessing this object is the same object that foo pointed to.

This confuses me, because I expected that writing delete obj deleted the object that obj was pointing to in memory—not just the variable obj.

Is this because JavaScript's Garbage Collector is working on a retain/release basis, so that if I didn't have any other variables pointing to the object, it would be removed from memory?

(By the way, my testing was done in Safari 4.)

Sam
  • 6,961
  • 15
  • 44
  • 63
Steve Harrison
  • 103,209
  • 15
  • 83
  • 71
  • 8
    For your reference. https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/delete_Operator – Daniel A. White Apr 12 '09 at 23:37
  • Full article on the delete keyword http://webcache.googleusercontent.com/search?q=cache:auElwuFsub0J:perfectionkills.com/understanding-delete/+delete+javascript&cd=2&hl=en&ct=clnk&client=safari – Vitim.us Dec 17 '12 at 23:08
  • 3
    Link above should be: http://perfectionkills.com/understanding-delete – johnmdonahue Jun 13 '13 at 19:32
  • 1
    @Steve Harrison delete is not for delete an object in javascript delete use for remove an object key in your case `var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;` object is not deleted check `obj` delete usage: `delete obj.helloText` and then check `foo now foo is an empty object` – Umair Ahmed Apr 15 '16 at 10:48
  • 2
    @UmairAhmed, Free translation: """ `delete` is not for deleting objects in javascript. `delete` is used for removing an object key. In your case `var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;`, the object is not deleted. check `obj`. Next, run `delete obj.helloText` and you can see that `foo` now points to an empty object. """ – Pacerier Mar 23 '17 at 01:21
  • For whom this might be helpful: if you are defining properties with `Object.defineProperty()`/`Object.defineProperties()`, any properties not explicitly set to `configurable: true` can not be deleted. Heh, I was banging my head on that one for a while. – Phil Tune Mar 12 '18 at 02:56

11 Answers11

461

The delete operator deletes only a reference, never an object itself. If it did delete the object itself, other remaining references would be dangling, like a C++ delete. (And accessing one of them would cause a crash. To make them all turn null would mean having extra work when deleting or extra memory for each object.)

Since Javascript is garbage collected, you don't need to delete objects themselves - they will be removed when there is no way to refer to them anymore.

It can be useful to delete references to an object if you are finished with them, because this gives the garbage collector more information about what is able to be reclaimed. If references remain to a large object, this can cause it to be unreclaimed - even if the rest of your program doesn't actually use that object.

Jesse Rusak
  • 54,013
  • 12
  • 95
  • 102
163

The delete command has no effect on regular variables, only properties. After the delete command the property doesn't have the value null, it doesn't exist at all.

If the property is an object reference, the delete command deletes the property but not the object. The garbage collector will take care of the object if it has no other references to it.

Example:

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'

(Tested in Firefox.)

Guffa
  • 640,220
  • 96
  • 678
  • 956
  • 39
    If this is executed in the global scope, your `x` variable becomes just a property on the global `window` object, and `delete x;` really does remove the `x` variable altogether. – Crescent Fresh Apr 13 '09 at 01:07
  • 18
    @crescentfresh: It's only a property if it's implicitly declared. If it's explicitly declared as in the example, it's a global variable and can not be deleted. – Guffa Apr 13 '09 at 15:19
  • 1
    Why the downvote? If you don't explain what you think is *wrong*, it can't improve the answer. – Guffa Oct 24 '12 at 07:33
  • I would down vote this if I had the rep... deleting x most certainly has an effect – Tarynn Mar 26 '13 at 20:38
  • 1
    @Tarynn: You are mistaken. You can't delete a variable, only a property. Try the code in the answer and see for yourself. – Guffa Mar 26 '13 at 21:28
  • @Guffa I hit f12 and went to console... Typed: var x = new Object(); Typed: x.y = 42; Typed: delete x; Typed: alert(x.y); Received: "'x' is undefined" It is you sir who is mistaken – Tarynn Mar 28 '13 at 14:35
  • @Guffa for completeness I tested this in IE10, Chrome, and Firefox IE10 and firefox deleted x, chrome would not – Tarynn Mar 28 '13 at 14:40
  • @Tarynn: Then you are doing something wrong in your test. I retested this in IE10, Chrome and Firefox, and neither deletes the variable x. http://jsfiddle.net/Guffa/YzQaW/ If you find a browser where the `delete` command actually deletes a variable, you should report that as a serious bug, because it should never do that. See https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/delete – Guffa Mar 28 '13 at 14:48
  • @Guffa are you saying you are observing a different behavior IN CONSOLE then what I reported? I see the behavior you describe in the jsfiddle example, but IN CONSOLE it behaves as I described. – Tarynn Mar 28 '13 at 18:10
  • 4
    @Tarynn: I see, that's where the problem is. If you do this in the console, for some reason `x` will not be a proper variable in some browsers, but a property in the `window` object. This is of course a problem with the console, and doesn't reflect how code is normally executed. – Guffa Mar 28 '13 at 19:26
  • 2
    @Guffa After a bunch of research I have to concede it was probably a good thing I didn't have enough rep to down vote. My sincerest apologies, and thanks for taking the time to show me what was happeneing... Here is an indepth explination: http://perfectionkills.com/understanding-delete/#firebug_confusion – Tarynn Mar 28 '13 at 20:13
  • this is not correct anymore, because deleting an object `delete x` in your case will delete the reference to that object, so running your code will cause reference error because x will not be defined after you invoke delete x for the first time. – chao Jul 02 '13 at 19:11
  • 1
    @chao: You are mistaken. Doing `delete x` has no effect if `x` is a variable. It can only be used to delete object properties. Try it out for yourself. – Guffa Jul 02 '13 at 21:33
  • @Guffa Hi. Pretty interesting. I tried before, and I tried now. See here [link](http://s21.postimg.org/bxlrnbpc7/delete.jpg). But what you pointing out I also found in documentation [link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_operators#delete). So I am confused now. Documentation says nothing about deleting local var, but I am getting reference error. Is there any explanation or I am doing something wrong? btw. I am using firefox 21.0 on suse linux. – chao Jul 02 '13 at 22:34
  • 2
    @chao: I see. You are having the same problem as Tarynn (see earlier comments). When you do this in the console it doesn't work the same as in real code. – Guffa Jul 02 '13 at 22:37
  • @Guffa ah, lazy me. i did not read all of previous comments. i though that new versions of firefox change the way of deleting variables. anyway, thanks. i hope they would correct this in firebug. cheers. – chao Jul 02 '13 at 22:58
  • Got `ReferenceError` on line 8 on FF 23 – Gill Bates Sep 11 '13 at 11:52
  • @GillBates: The empty line? – Guffa Sep 11 '13 at 12:13
  • @GillBates: I have Firefox 23.0.1 and I retested the code with it, and I get no error. http://jsfiddle.net/Guffa/YzQaW/ – Guffa Sep 11 '13 at 13:09
  • Seems delete keyword also works on an array element. I had an object array that was holding window.open() references. Upon closing the window, I removed the window reference from the array using `array.splice()`. Still I was able to see the window object counts in chrome profiler. The object was not collected by GC. Using `delete array[index]` did the trick. Any comments @Guffa – Khadim Ali Feb 01 '16 at 13:58
  • 1
    @AliLee: The `splice` method returns the removed items in a new array object, so the GC might have had trouble figuring out that the window object was actually unused. Using `array[index] = null;` might have the same effect on the GC as deleting the item. The GC should eventually pick up and collect all unused objects, but it's a good idea to make the work easier. – Guffa Feb 01 '16 at 21:13
57

"variables declared implicitly" are properties of the global object, so delete works on them like it works on any property. Variables declared with var are indestructible.

Alex
  • 571
  • 4
  • 2
24

Coming from the Mozilla Documentation, "You can use the delete operator to delete variables declared implicitly but not those declared with the var statement. "

Here is the link: https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Operators:Special_Operators:delete_Operator

David Ackerman
  • 11,809
  • 6
  • 21
  • 19
5

delete is not used for deleting an object in java Script.

delete used for removing an object key in your case

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

object is not deleted check obj still take same values delete usage:

delete obj.helloText

and then check obj, foo, both are empty object.

Derlin
  • 8,518
  • 2
  • 22
  • 42
Umair Ahmed
  • 5,537
  • 2
  • 25
  • 32
2

Aside from the GC questions, for performance one should consider the optimizations that the browser may be doing in the background ->

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

It appears it may be better to null the reference than to delete it as that may change the behind-the-scenes 'class' Chrome uses.

fgb
  • 17,739
  • 2
  • 33
  • 50
sksizer
  • 221
  • 2
  • 2
2

Setting a variable to null makes sure to break any references to objects in all browsers including circular references being made between the DOM elements and Javascript scopes. By using delete command we are marking objects to be cleared on the next run of the Garbage collection, but if there are multiple variables referencing the same object, deleting a single variable WILL NOT free the object, it will just remove the linkage between that variable and the object. And on the next run of the Garbage collection, only the variable will be cleaned.

Pedro Justo
  • 3,319
  • 1
  • 13
  • 21
2

Just found a jsperf you may consider interesting in light of this matter. (it could be handy to keep it around to complete the picture)

It compares delete, setting null and setting undefined.

But keep in mind that it tests the case when you delete/set property many times.

garek
  • 361
  • 3
  • 10
1

I stumbled across this article in my search for this same answer. What I ended up doing is just popping out obj.pop() all the stored values/objects in my object so I could reuse the object. Not sure if this is bad practice or not. This technique came in handy for me testing my code in Chrome Dev tools or FireFox Web Console.

Craig London
  • 642
  • 1
  • 8
  • 14
1

IE 5 through 8 has a bug where using delete on properties of a host object (Window, Global, DOM etc) throws TypeError "object does not support this action".

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
}

Later if you need to check where the property has a meaning full value use el.foo !== undefined because "foo" in el will always return true in IE.

If you really need the property to really disappear...

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

if your need to use the host object with host api...

el.parent.removeChild(el._host);
0

This work for me, although its not a good practice. It simply delete all the the associated element with which the object belong.

 for (element in homeService) {
          delete homeService[element];
  }
Hank
  • 161
  • 3
  • 12
  • what is best practice? I remember reading that the delete operator was not best practive for deleting object properties. I believe I read this in Crockford's JavaScript book, but can't dig it up at the moment. – zero_cool Mar 01 '19 at 17:52