67

The behaviour of the delete operator seems very complicated and there are many misunderstandings about what it actually does. To me, it seems that reassigning something to undefined will more reliably do what you would expect.

I've never seen the delete keyword in Javascript actually used in non-example code and I am wondering if it is particularly useful for anything. Does delete have any purpose that cannot be acheived by reassignment to undefined? Is it used at all in any of the famous libraries (e.g. jQuery, dojo, backbone, etc)?

Brian Tompsett - 汤莱恩
  • 5,195
  • 62
  • 50
  • 120
Peter Olson
  • 121,487
  • 47
  • 188
  • 235
  • 1
    The behavior of `delete` isn't complicated at all. But it **really** shouldn't have been called `delete`. JavaScript being syntactically similar to C++, using an operator C++ has but doing something *completely different* with it was a bit of an oops and has caused all of this confusion. (If it were called `remove`, I bet people wouldn't be nearly so confused.) – T.J. Crowder Jan 20 '12 at 18:07
  • http://perfectionkills.com/understanding-delete/ – Raghu Jan 20 '12 at 17:22

6 Answers6

75

Does delete have any purpose that cannot be acheived by reassignment to undefined?

Yes. If you want to unmask a property from a prototype or cause in, hasOwnProperty, and for (...in...) to not record the property as existing then delete is appropriate.

let set = {};

set._x = true;

alert('_x' in set);  // true

set._x = undefined;

alert('_x' in set);  // true

delete set._x;

alert('_x' in set);  // false

EDIT: As T.J. Crowder explains:

The purpose of the delete operator is to completely remove a property from an object, whereas setting a property to undefined just sets the property to undefined.

This matters in its own right, but it also matters when you're using inheritance, because if O derives from P

let P = { prop: 42 };
let O = Object.create(P);  // P is O's prototype.

when you retrieve O.prop, you get the value of prop from O if O has a property with that name (even if its value is undefined), but if O doesn't have the property at all, then the value will be retrieved from P.prop instead.

console.log(O.prop);  // "42" since O doesn't have its own prop, but P does.
O.prop = undefined;
console.log(O.prop);  // "undefined" since O has its own prop.
delete O.prop;
console.log(O.prop);  // "42" since the delete "unmasked" P.prop.
Mike Samuel
  • 109,453
  • 27
  • 204
  • 234
25

As Mike Samuel points out in his answer, one of the most common usages of delete is when you are treating an object as a "property bag" that associates names with values. There is logically a difference between "this name is now mapped to some bogus value" and "this name is not mapped at all". "delete" achieves the latter.

That's all reasonably well understood. I thought I might add an interesting historical note regarding the JScript 1.0 through 5.0 engines.

In those original Microsoft implementations of JScript we used OLE Automation-style IDispatch objects to implement expando objects. IDispatch of course works by associating a name with a "dispatch id", which is simply an integer. To invoke dynamically, first you ask the dispatch object to give you the dispatch ID associated with a name, and then you say "now invoke the method associated with this ID, given these arguments".

That's all well and good. But one of the requirements of the IDispatch contract is that the mapping from name to dispatch ID be stable over the entire lifetime of the object. So if someone says "add property Foo to this object", then we might decide that property Foo is associated with dispatch identifier 0x1234 in that object. From that moment on, every time the object is asked for the dispatch identifier of "Foo", it must give back 0x1234, even if Foo is deleted and subsequently added again. This permits a caller to maintain their own fast cache of name/dispid pairs rather than always having to ask the object on every invocation.

The practical upshot of that is that "delete" does not in any way lessen the memory burden on the object in that implementation! When you delete a property (in the original implementation) we must add a bit to the object marking that dispatch identifier as deleted, but we must retain all the information about the name/id pairing in case that name ever comes back. Adding a huge number of properties to an object and then deleting all of them does not shrink the object in memory.

The JScript engine has of course been completely rewritten since my time (except for, I believe, the parser and lexer) so I have no idea if the engine still has this unusual quirk. It would be interesting to find out.

Eric Lippert
  • 612,321
  • 166
  • 1,175
  • 2,033
11

If you do

 delete Foo.Bar;

it deletes the property Bar from object Foo entirely

 Foo.Bar = undefined

merely sets Bar property to undefined and Foo.Bar still exists

parapura rajkumar
  • 22,951
  • 1
  • 49
  • 82
3

The other answers are explaining the motivation behind the delete keyword. I would like to add that as of 2017, browser do deallocate memory both when deleting a property and when setting the property to undefined.

Consider this example (source of roughSizeOfObject()):

> var obj = {a:42,b:"b"}; roughSizeOfObject(obj)
26
> obj.a = undefined; roughSizeOfObject(obj)
18
> delete obj.a; roughSizeOfObject(obj)
10
> obj.b = undefined; roughSizeOfObject(obj)
8
> delete obj.b; roughSizeOfObject(obj)
0

The example comes from Chrome 61 (64-bit) console (note that all characters in String are internally encoded as 16-bit unsigned integer).

syntagma
  • 20,485
  • 13
  • 66
  • 121
  • But in MDN site it's mentioned that "Unlike what common belief suggests, the delete operator has nothing to do with directly freeing memory. Memory management is done indirectly via breaking references, see the memory management page for more details.". So which on is true? – Vishal-Lia Apr 24 '18 at 10:19
  • @Vishal-Lia I would say that MDN may be outdated in this regard. – syntagma Apr 24 '18 at 10:20
  • May be MDN is right. In implementation of roughSizeOfObject(), the size in bytes is hard-coded depending on type and if that property is available in object. And I think Garbage collector will deallocate memory later. Please correct me if I'am wrong. – Vishal-Lia Apr 24 '18 at 10:49
1

You can check the answer of the following link Can I set variables to undefined or pass undefined as an argument? which explains the difference in a very detailed way.

Summary:

You can certainly assign undefined to it, but that won't delete the variable. Only the delete object.property operator really removes things.

delete is really meant for properties rather than variables as such. Browsers will let you get away with straight delete variable, but it's not a good idea and won't work in ECMAScript Fifth Edition's strict mode. If you want to free up a reference to something so it can be garbage-collected, it would be more usual to say variable= null.

Community
  • 1
  • 1
Adel Boutros
  • 9,733
  • 6
  • 48
  • 89
0

Well, you'd end up with an element in your object that contains the value undefined. The key wouldn't be gone.

James McLaughlin
  • 18,363
  • 2
  • 45
  • 56