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.