The Great Mystery of the Tilde(~)

When was the last time you typed in a tilde? Did you even know that little squiggle on the top left corner of your keyboard is called a tilde? More importantly to this blog, do you know what the tilde does in JavaScript? Probably not, but you'll soon find out.

The tilde is an operator that does something that you'd normally think wouldn't have any purpose. It is a unary operator that takes the expression to its right performs this small algorithm on it (where N is the expression to the right of the tilde): -(N+1). See below for some samples.

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

So, unless you actually have an application that needs to run this algorithm on numbers – which I doubt very many people do – how are we going to use this squiggly little character to our advantage?

Converting Strings to Numbers

The tilde character needs a numeric value for N, so if you place it in front of a string expression, it will convert that string to a number for the calculation. That still leaves us with a not-so-helpful number because it doesn't match the number that was in the string. If you're any good at mathematics, though, you'll realize that if you run this algorithm twice, you'll get the same number that you started with. With a string, it'll convert it to a number, then change it, then change it back to the number.

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

As shown in the above code example, you can also convert true and false into 1 and 0 respectively. I don't see quite as many uses for this, but I wouldn't doubt that there were some. Also, I realize that there are plenty of ways to convert strings into numbers and I'm not claiming this is the best way. I'm just saying that this is a viable option.

~-1 is 0

If you look back at the first code sample, you'll see that using ~ on -1 converts it to 0. The number 0 is a falsey value, meaning that it will evaluate to false when converted to a Boolean. That might not seem like a big insight at first, but remember functions like indexOf will return -1 when the query is not found. This means that instead of writing something similar to this:

if (someStr.indexOf("a") >= 0) {
	// Found it
} else  {
	// Not Found

You can now have fewer characters in your code so you can write it like this:

if (~someStr.indexOf("a")) {
	// Found it
} else  {
	// Not Found

I think this might be a more common use case, and probably the only way I'll actually use tilde unless I run into a situation where other string conversions are hard to read within the context their being used (such as here: num = 1 + +"2").

ADDED 3/6/2012: One thing you need to consider before using the tilde as a means to convert strings to numbers (as pointed out in the comments by Beej Jorgensen) is that it will convert into an integer, not a decimal number. "3.14" and 3.14 will both end up as just 3 (with double tildes). Also somewhat important to note: ~ is a Binary NOT operator, which means that it doesn't actually run the algorithm stated above. The algorithm above is just one way for you to be able to understand what the outcome will be when this operator is applied to it (Thanks Danny Ayers and Anonymous for pointing this out).

Reining In the Tilde

So, did you actually know what the tilde operator did? Or that it even existed? I know I didn't until recently, and I probably would have gotten along just fine without ever learning about it, but it's always fun to know something that most others don't know, you know? If you can think of anything other fun things you can do with the tilde, let me know in the comments below! Also, let the rest of the JavaScript programming community in on this little-known operator by sharing this post with your friends via the buttons below. As always: Happy Coding!

About the Author

Author: Joe Zim

Joe Zim

Joe Zimmerman has been doing web development ever since he found an HTML book on his dad's shelf when he was 12. Since then, JavaScript has grown in popularity and he has become passionate about it. He also loves to teach others though his blog and other popular blogs. When he's not writing code, he's spending time with his wife and children and leading them in God's Word.

  • Guest

    I think you got wrong the second example of indexOf:
    if (~someStr.indexOf(“a”)) {

     // *Not* Found

    } else  {

     // Found it


    • Guest

      Nope, you were right, my example is wrong, sorry :)

      • Joe Zimmerman

        Yea, I saw another site that talked about the tilde operator and they did actually have it backward. I made sure to check and double check to make sure it was right because this sort of logic can get a little confusing sometimes.

        • Gregor

          Note that the Crock says that bitwise operators are much slower in js than in languages like c, because all js numbers are floats– they have to be converted before any bitwise ops take place.

          • Joe Zimmerman

             Now that you mention it, I remember him saying that. It’s been quite a while since I’ve read anything by the great DC.

  • Stefan Matsson

    Very nice article. Never seen the tilde operator (in this context) before during my four years as a web developer. Some notes on your article: 
    * The tilde operator is slightly slower than doing “indexOf(x) >= 0” (not by much)
    * You shouldn’t use code as “num = 1 + + “2” in the first place since that piece of code till break when using a compressor (like JSMin). The compressed output of that line would be “1++”2″” which is not a proper statement (resulting in “SyntaxError: Unexpected string”). :) 

    I really enjoy your blog. Keep up the good work!

    • Joe Zimmerman

      Thanks, I didn’t even think about the compression breaking the code. I just know that many people will put a + before a string to convert it to a number.

      • Stefan Matsson

        The plus sign is the best way of converting a string to a number, mainly because it uses the valueOf function (parseInt and parseFloat does not). I wrote a post about it some time ago if anyone is interested (section “Converting to numbers”):

        Anyway, just wrap your convert statement in parentheses and you are good to go with compression. :) 
        var x = 1 + (+”2″); 

        • Joe Zimmerman

           Another great point. Thanks!

  • anonymous

    ~ is a Logical NOT operator, not a small math computation: each bit in its operand is flipped. Saying that it does a little calculation is misleading.

    • Joe Zimmerman

       Sorry if I mislead anyone, but it is only because I was mislead myself. I only reported the information that I was given.

    • AdamTolley

      bitwise not logical – it works on the bits of the number as represented in binary – its the peculiarity of two’s complement encoding of numbers that results in its behavior in integers.

      logical operators are things used in logic, the ones you are more used to like ! for not in js.

  • mattsnider

    Have you done any analysis on performance? I’ve been using tilde for a while now, in place of “> -1”, and have always been curious if the bitwise operation and falsy evaluation was more performant. I doubt it changes performance much, but might be interesting to analyze.

    • Joe Zimmerman

       I have not done any analysis myself, though I have been told (in a comment earlier on this post) that is was slightly slower, though, the difference seems to be negligible.

    • Eugene Poltorakov
      • mattsnider

        Thanks Eugene. About a 40% performance boost for me using “<" in Chrome… that's a pretty good argument for not using "~".

  • Danny Ayers

    Just to clarify anonymous’ comment, ~ is a bitwise NOT operator (! is the logical NOT). Like a lot of other languages, Javascript inherits it from C. Your example use of it looks like a handy little idiom, but more typically it’s useful where algorithms can be expressed in low-level operations, i.e. bit-shuffling, alongside operators like &, |, ^, <>.

    • Joe Zimmerman

       Yea, which is why I suppose so few people know about it. In high level languages like JavaScript, not a whole lot of people use bitwise operations.

  • Beej Jorgensen

    Also internally ~ runs the number through ToInt32.  So:

    ~~3.14 === 3

    • Joe Zimmerman

       Wow, I should have noticed that. It’s definitely good to bring up the fact that it converts it to an integer instead of leaving the decimals intact.

  • Towrywang


  • elliottcable

    Usefully, it’s one of the only operators that’s *only* interpretable as unary; it’s an excellent way to force the parser to interpret a particular bit of code as an expression instead of a statement. I use it facetiously all the time on the throwaway non-results of anonymous functions, simply to force said anonymous functions to be parsed as expressions. As an added benefit, it also can’t fuck up the parsing of previous lines if you are the type to omit semicolons.

    // Without superfluous operator, we need to surround the anonymous ‘scoping’ function in
    // parenthesis to force it to be parsed as an expression instead of a *declaration*, which allows
    // us to immediately function-call-pattern it.
    // ...

    // By inserting a superfluous operator, we can omit those parentheses, as the operator forces the
    // parser to view the anonymous function as an expression *within* the statement, instead of as the
    // statement itself, which saves us a character overall, as well as some ugliness:
    // ...

    // But, in all of the above examples, if one is depending on ASI, and doesn't needlessly scatter
    // semicolons all over their code out of ignorance, a prepended semicolon is necessary to prevent
    // snafus like the following:
    var foo = 4
    // ...
    // ... in which case, the variable `foo` would be set to a crazy addition / concatenation involving
    // the (probably non-existent) *return value* of our anonymous ‘scoping’ function.

    // Hence, our friend the bitflip:
    var foo = 4
    // ...
    // ... he solves all of our problems, by disnecessitating the prepended semicolon *and* the wrapping
    // parentheses.

    • Joe Zimmerman

      That’s a very interesting use. The only thing would be to get everyone on board with this so it’s recognized by many as the way to do an IIFE.

    • trusktr

      I like this!

  • vikas

    thanks for this post ….really helpful to understand this

  • Jonathan Petitcolas

    Nice post on this very mysterious operator. I was curious to benchmark performances for “tilde-ous” casting, and indeed: it is pretty slow: (and not easy to read).

    • Joe Zimmerman

      Go back and look at the numbers given by Firefox 25 and IE11. Looks to me like parseInt is the clear loser on those browsers. judging by these numbers, I would predict that in the future, the tilde will be better optimized in nearly all browsers. parseInt is FAR from slow in any of the browsers, and I definitely agree that the double-tilde doesn’t make much sense compared to “parseInt”, so it’s still up to the developer.

      I wasn’t really trying to push people to use the Tilde. I was just showing the options. In the end, it’s always up to you(r team) to decide which methods you use.

    • borto matheo

      for me on chrome ~~ is the faster