~, !, +, & –

Does that headline look like a bunch of cussing to you? I was hoping it would be offensive.

I’m also looking forward to see how it’s covered by the tech aggregators like Digg and Reddit. And I want to see if perhaps people land here as the result of searching for a bunch of punctuation.

Mostly I wanted to talk about JavaScript types, and how you can convert from boolean to numeric and vice versa.

This is going to be a pretty freeform discussion. If you get bored jump right to the end–there’s a trick there that’s pretty useful.

Big Mistake. Big, Big Mistake

Douglas Crockford has often mentioned that the dual usage for the plus symbol is a mistake in JavaScript. He’s right. It’s used both for numeric addition and for string concatenation. This trips programmers up all the time and there’s just no excuse for it. No upside. Another symbol should have been used for string concatenation.

The common solution to this is to wait until you get tripped up, find which term is being mistaken for a string, and then use one of the functions that JavaScript provides that converts strings to numbers. I prefer to use yet another usage of the plus symbol to do that work. I use the unary version of plus.

For example:

num = 1 + +"2"; //num is assigned the value 3

See the space between the plus signs? Yeah, that’s critical. You don’t want to mistake those two pluses for the symbol ++, the increment operator.

A unary minus works too, if you happen to want the negated version.

num = 1 - -"2"; //num is assigned the value 3, again

There’s another cool use for the plus sign. It’ll turn true and false into numbers.

num=+true; // num is 1
num=+false; //num is 0
num=-true; // num is -1
num=-false; //num is 0

So we turn true and false into 1 and 0 with unary plus. How do we turn 1 and 0 into true and false? One way is with the bang (exclamation point). In this case, we actually use a double-bang or “bang bang.” (Google “bang bang cher” and find out that long before William Hung banged, Cher banged.)

bool = !!1; //bool is true
bool = !!0; //bool is false

The first bang casts from the number to a Boolean, and the second undoes the logical not that was performed by the first bang.

You still following? How about a curve ball?

num = 1 + ~~"2"; //what the hell is that?

Welcome to the tilde. The result is 3 again, but what’s with the squiggles? The squiggle, of course, is the tilde operator. JavaScript programmers learn it and then promptly forget about it. But it plays a part in one of my favorite JavaScript tricks. We’ll see that right at the end. For now, let’s look at what it does to some values.

console.log(~-2); //1
console.log(~-1); //0
console.log(~0); //-1
console.log(~1); //-2
console.log(~2); //-3
console.log(~true); //-2
console.log(~false); //-1

As you can see, ~ is doing -(N+1). For fun, let’s throw a unary minus into the mix.

console.log(-~-2); //-1
console.log(-~-1); //0
console.log(-~0); //1
console.log(-~1); //2
console.log(-~2); //3
console.log(-~true); //2
console.log(-~false); //1

So -~N is the same as N+1.

Now let’s look at the bang symbol along with the tilde.

console.log(!-2); //false
console.log(!-1); //false
console.log(!0); //true
console.log(!1); //false
console.log(!2); //false
console.log(!true); //false
console.log(!false); //true

And for fun, let’s put the bang and the tilde together…

console.log(!~-2); //false
console.log(!~-1); //true
console.log(!~0); //false
console.log(!~1); //false
console.log(!~2); //false
console.log(!~true); //false
console.log(!~false); //false

Now that’s interesting. Only the value -1 makes it out alive with a true value. And come to think of it, there’s something special about -1. It’s a common sentinel value returned by functions that return indexes (JavaScript’s indexOf() is a great example, but you may have your own functions that return -1 as a sentinel value).

WTF?

What am I talking about? Suppose you want to know where the letter “s” is in a string. Well, you either get a number back that tells you where it is, or you get a -1 back telling you, hey buddy, no “s” in this string. So you end up with code like…

if (index>=0) {
 //found it
} else {
 //didn't
}

or

if (index>-1) {
 //found it
} else {
 //didn't
}

or

if (index!=-1) {
 //found it
} else {
 //didn't
}

But with what we now know about tilde, we can just do this…

if (!~index) {
 //found it
} else {
 //didn't
}

Or, finally, we can turn the logic around and do this…

if (~index) {
 //didn't find it
} else {
 //did
}

Credit

I’ve seen this trick a few times before. Add a comment to this post if you can help me find other places this has been mentioned.

Web Reflections