On the ephemeral nature of delete

Delete in JavaScript is a peculiar beast. Witness:

typeof x; // outputs undefined
delete x; // outputs true even though x is not defined
typeof x; // outputs undefined

So, it is possible to delete an undefined variable in the global scope (well, this is not true, but it will explained in detailed later in this article). Let’s try deleting a defined variable in the global scope:

typeof y; // outputs undefined
var y = 1;
typeof y; // outputs number
delete y; // outputs true
typeof y; // outputs undefined

It’s clear that deleting a variable in the global scope works as expected. How about deleting array elements?

typeof arr; // outputs undefined
var arr = [1, 2, 3, 4]; // outputs true even though y is not defined
typeof arr; // outputs object
typeof arr[2]; // outputs number
delete arr[2]; // outputs true
typeof arr; // outputs object
typeof arr[2]; // outputs undefined
arr; // outputs [1, 2, undefined, 4]
arr.length; // outputs 4

It’s peculiar behavior, isn’t it? Deleting an element in the array sets the element to undefined, but doesn’t actually remove it from the array. After deleting the element, the array length indicates 4 elements, of which 3 are defined and 1 undefined. It’s good to keep this peculiarity in mind, when working extensively with arrays. To actually remove an element from an array, the splice() method can efficaciously be used:

arr.splice(2, 1); // delete 1 element, starting from the 3rd element
arr; // outputs [1, 2, 4]
arr.length; // outputs 3

Now, lets investigate the behavior of deleting an object member:

var objection = function() {
 
this.pub = 456;
var priv = 123;
 
var privmethod = function() {
 
return "this is a private method";
 
}
 
this.pubmethod = function() {
 
return "this is a public method";
 
}
 
this.printpub = function() {
 
return this.pub;
 
}
 
this.printpriv = function() {
 
return priv;
 
}
 
this.deletepub = function() {
 
delete this.pub;
 
},
 
this.deletepriv = function() {
 
delete priv;
 
}
 
};
 
var obj = new objection(); // creating new obj
 
obj.pub; // outputs 456
obj.priv; // outputs undefined
obj.pubmethod(); // outputs "this is a public method"
obj.privmethod(); // outputs TypeError (because its a private method)

This is an aside but we can see that by defining variables and methods with the var keyword, they retain private behaviour of the object. Let’s try deleting a public variable:

obj.pub; // outputs 456
obj.printpub(); // outputs 456
delete obj.pub; // outputs true
obj.pub; // outputs undefined
obj.printpub(); // outputs undefined

We can clearly delete public members of objects from outside the object. How about deleting from a method within the object?

obj.pub; // outputs undefined
obj.printpub(); // outputs undefined
obj.pub = 456; // redefining obj.pub
obj.deletepub();
obj.pub; // outputs 456
obj.printpub(); // outputs 456

That too works as expected. Now let’s try deleting a private variable:

obj.priv; // outputs undefined
obj.printpriv() // outputs 123
delete obj.priv; // outputs true even though priv has not been deleted
obj.priv; // outputs undefined
obj.printpriv() // outputs 123

Clearly, one cannot delete a private variable from outside the object. It’s important to note that deleting a private variable returns true but it’s clear from the preceding example that the variable has not been deleted. What if we try to delete the private variable from a method?

obj.priv; // outputs undefined
obj.printpriv() // outputs 123
obj.deletepriv();
obj.priv; // outputs 123
obj.printpriv() // outputs 123

It doesn’t work either. Hence, private variables cannot be delete’d.

Is it possible to delete whole objects? Let’s try it out:

typeof obj; // outputs object
delete obj; // outputs true
typeof obj; // outputs undefined
obj; // throws a ReferenceError

This works because obj was created as part of the browser instance, and thus obj is actually a property of the window object. In other words, obj is actually window.obj. As a rule of thumb, if it is public property on an object, it can be delete’d.

Our very first example was about deleting a variable in the global scope, and that example showed that the variable could be deleted. That’s not quite true. That variable, just like obj, was a property of the window object, so it could be deleted. To test whether a variable in the global scope can be deleted, it’s best to experiment in a standalone JavaScript engine.

There are several standalone JavaScript engines which you can use. Rhino is a (slow) engine by Mozilla, v8 is a fast engine by the Google chaps. Take your pick – I went with rhino because it came packaged with Fedora 12 :)

So, launching rhino in interactive mode, lets retry the first few examples:

typeof x; // outputs undefined
delete x; // outputs a TypeError
typeof x; // outputs undefined

Aha, we get a TypeError as rhino fails in deleting property x of ‘null’.

typeof y; // outputs undefined
var y = 1;
typeof y; // outputs number
delete y; // outputs false
typeof y; // outputs number

Sure enough, rhino refuses to let us delete the variable. But, what if the variable is not defined with the var keyword?

typeof z; // outputs undefined
z = 1;
typeof z; // outputs number
delete z; // outputs true
typeof z; // outputs undefined

This behavior is indeed peculiar but it makes sense when one considers that all variables in the global scope are part of the global object:

this; // outputs [object: global]
this.y; // outputs 1

Thus, as a rule of thumb, remember that explicitly declared variables cannot be deleted and implicitly declared variables can be deleted. If this makes no sense whatsoever, this article explains the underlying rationale.

Finally, what about eval()’ed code?

eval("var e = 1;");
typeof e; // outputs number
delete e; // outputs true
typeof e; // outputs undefined

Wait a minute. What gives? Why is code that is eval()’ed treated differently? That’s because the Ecma JavaScript specification explicitly treats eval()’ed code differently: anything that is eval()’ed can be deleted (again, this article explains why that is).

That’s it for this week. Next week, we will explore the nature of prototypical inheritance.

This entry was posted in Technology. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">