Javascript Style Tip: Use "in" and "delete" #
Javascript provides two very handy operators, in and delete.
Consider this code fragment:
var obj = {
foo : 'quux',
bar : 'baz',
doSomething : function () {
// do something...
}
};
So, we’ve created an object, and then some other things happen. Later in the code, we want to remove the “foo” property, so we do this:
obj.foo = undefined;
Still later, we only want to do something if the foo property has not been unset, so we check it:
if ( obj.foo !== undefined ) {
// do something
}
That works, and it’s fairly common, but it’s klunky, and not as readable as this:
delete obj.foo;
if ( 'foo' in obj ) {
// do something
}
The first one says, Delete “foo” from the object.
The second asks, Is “foo” in the object?
The difference between the first and second approaches is that the second uses intuitive wording in the code.
Note: You must use delete
if you want to use in
. Setting something to undefined
manually will not cause it to return false when testing whether the property is in
the object.
As an added bonus, using the delete
operator also removes the property from the for/in iteration loop, since it actually removes it from the object’s key list rather than simply setting it’s value to undefined
.
var obj = {asdf:'foo',bar:'baz'};
obj.asdf = undefined;
for ( var i in obj ) {
console.log(i,obj[i]);
}
// outputs:
// asdf undefined
// bar baz
var obj = {asdf:'foo',bar:'baz'};
delete obj.asdf;
for ( var i in obj ) {
console.log(i,obj[i]);
}
// outputs:
// bar baz
Note: you’ll need to wrap the “in” statement in parentheses if you want to negate it. For example, this is a bug:
var obj = { asdf:'foo',bar:'baz' };
var f = 'quux';
if ( !f in obj ) {
alert( 'not there!' );
}
The alert will never fire. Can you figure out what’s happening? Here’s a clue:
var obj = { 'false':1, asdf:'foo', bar:'baz' };
var f = 'quux';
if ( !f in obj ) {
alert( 'not there!' );
}
Now the alert will fire. What’s up?
The order of operations is this:
- Process the !f, which converts ‘quux’ to a boolean (true), and then gets the opposite (false).
- The “in” operator converts the value back to a string, and false.toString() is the string 'false’.
- Since 'false’ is not a key in the object, the “in” operator returns false, and the conditional fails.
In the second case, since the string 'false’ is a key in the object, the “in” operator returns true, and the conditional fires. Of course, using “false” as a key in an object is a really stupid thing to do, but if some bunk data comes into your program somehow, it can happen. Always wrap your “in” clauses in parentheses, and you’ll never have a problem. In this case, it works as expected:
var obj = { asdf:'foo', bar:'baz' };
var f = 'quux';
if ( !(f in obj) ) {
alert( 'not there!' );
}
Update
I’m finding that a lot of people are hitting this page with search queries that seem to indicate they’re looking to remove a style property from a Dom node. delete
won’t help you much there, since the style
property is a get-and-set-only property. (IE, you can read from and write to it, but you can’t delete from it.)
Most of the time, you shouldn’t be messing with the style
property directly in Javascript, anyhow. Instead, add and remove semantically meaningful class names, and put the style information related to those states in the CSS. Of course that’s not always an option, I know. So, you can remove the inline setting by simply setting it to an empty string, like this:
document.body.style.background="red"; // turns the page red.
document.body.style.background=""; // turns the page back to whatever it was.
Cheers!