~, !, +, & -

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

About these ads

16 Comments

  1. July 5, 2008 at 11:26 am

    Neat. I used to do:

    if( 1+str.indexOf(foo) ){ /* found */ }else{ /* not found */ }

    but the following is like music to my ears.

    if( ~str.indexOf(foo) ){ /* not found */ }else{ /* found */ }

  2. rhettanderson said,

    July 5, 2008 at 3:19 pm

    Yeah, that’s a good one. I almost listed that as a possibility, but I thought I was going on a bit too long with the counter-examples. :-)

  3. Matt Kruse said,

    May 12, 2009 at 2:14 pm

    Your logic in the last two examples is backwards. It should be:

    if ( ~str.indexOf(‘match’) ) {
    // found it
    } else {
    // didn’t
    }

  4. Nosredna said,

    May 12, 2009 at 5:39 pm

    Thanks Matt. I’ll fix that.

  5. Rob said,

    December 15, 2009 at 6:29 pm

    The logic in the last two examples is still backwards. :-(

  6. Matt Huggins said,

    October 11, 2010 at 5:42 pm

    Interesting, but I think the last example just makes the code harder to read.

  7. January 17, 2011 at 9:03 pm

    Wonderful work! This is the type of information that should be shared around the net. Shame on the search engines for not positioning this post higher! Come on over and visit my web site . Thanks =)

  8. flo said,

    August 24, 2011 at 4:30 am

    true === !! ~”the examples should be reversed”.indexOf(“reverse”) :)

  9. K-Yo said,

    August 30, 2011 at 11:14 am

    Still backwards… more than 2 years later

  10. asfasf asfasfd said,

    November 1, 2011 at 3:23 pm

    So the person writing the tutorial couldn’t even get it straight. Yeah, using tilde’s in your code makes a lot of sense. Seems like something people do just to try to look smart and nothing more.. so error prone

  11. Sam Fentress said,

    March 15, 2012 at 8:21 pm

    Still backwards! I was scratching my head there for a little.

    For you last two examples, you should have

    if (~index) {
    //found it
    }

  12. D Soa said,

    April 3, 2012 at 3:31 pm

    Found this page searching for “javascript bang bang” which is exactly what I was looking for…what “!!” does. Thanks.

  13. Doug said,

    April 11, 2012 at 2:07 pm

    “The logic in the last two examples is still backwards.”

    Sounds to me like a good reason to NOT use these operators. After all, “index>=0″ only requires one more character than “!~index”, but is far easier to understand.

  14. Jasper Mogg said,

    June 20, 2012 at 8:19 pm

    OK, cool syntax, but at the same time doesn’t it make more sense just to use !=-1 ? A large proportion of programmers will react to ~index with a WTF…

  15. Keith Norman said,

    June 22, 2012 at 7:35 pm

    Yeah, ditto to the logic still being backwards.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: