Tuesday, May 25, 2010

JavaScript Double Bang

Lately I've noticed the use of the JavaScript double bang (!!) cropping up in our code. For example, I ran across this the other day:
var hasEmployeeBeenAdded = !!this.getEmployee(employeeID);
Now I'll have to admit that is a cool little trick. However, it got me to thinking...is this the best way to express this statement? While the value above is assigned to meaningful variable name, I'm debating with myself whether that is enough.

At first glance the double bang is non-sensical, since !!true is true and !!false is false. But taking a JavaScript "not" and inverting it with another "not" gives the handy side effect of doing a cast, or conversion, into a primitive boolean value.

Okay, so as is often the case with JavaScript, there are many ways to achieve the same result. Here are some examples, all returning false, that convert an undefined variable into a boolean primitive.

We have the previously mentioned double bang:
var myThing;
return !!myThing;
Then there is the ternary operation:
var myThing;
return myThing ? true : false;
Pretty clear what's going on there. So what about a plain old equality check:
var myThing;
return myThing !== undefined;
That seems to more clearly state what is going on, but it's just not as short as the double bang, and who wants to write an undefined check everywhere. Plus, it breaks if the variable is null or some other empty value.

So lets go back to the intent of the original code snippet.. a cast into a boolean. That brings me to this, using the JavaScript Boolean object to perform the conversion:
var myThing;
return Boolean(myThing);
That seems to state exactly what it is trying to do: casting the value of myThing into a boolean.

In his book "JavaScript: The Definitive Guide", a must have for any JavaScript developer, David Flanagan explains the effect of calling the Boolean object as a function (without the new keyword).
The values 0, NaN, null, the empty string "", and the undefined value are all converted to false. All other primitive values, except false (but including the string "false"), and all objects and arrays are converted to true.
In closing, I think the double bang might be a good interview question to try and trip somebody up, but I'm in favor of using the Boolean constructor for the sake of clarity.

2 comments:

  1. Don't forget about Ext.isEmpty and Ext.isDefined

    ReplyDelete
  2. I felt the same way about "!!" when I first saw it reading the jQuery code. Another one is coalesce using "||". I go back and forth about whether I'm writing clever code (which I don't want to do), or just using a feature of the language to get to short concise statements.

    It would be interesting to use !! for a month and see if it becomes second nature, but I have to agree Boolean(myThing) should not cause any developer to wonder what's going on while !! might.

    ReplyDelete