Friday, November 26, 2010

About Javascript shortcuts & trickery

There are lots of ways to write ECMA-/Javascript in shorthand. Some of those are just for the lazy ones, some of them are both, useful and short. And if I'm saying useful in that context, I mean fast(er).

Ladys and Gentlemen, here are my Top 3 Javascript shortcuts:

  • The double bitwise not (~~)

This is a pretty neat replacement / enhancement for Math.floor(). Example:

var rand = ~~(Math.random() * 100);

What happens here?
~ is a bitwise operator. Everytime you're using a bitwise operator in ECMA-/Javascript, the number of invocation is converted into a 32 bit integer internally (normally all numbers are hold as 64 bit integers).
Finally it negates each '0' to '1' and each '1' to '0'. Long story short, this only remains true for integers. It also has  a tremendous better performance than Math.floor(). So for instance 24.7157 is translated into 24.



  • The double negate (!!)

If you need to have a boolean expression from a given value, regardless which type it may be, you can call:

var someObject   = {foo: 'bar'},
    isFoo        = !!someObject.foo;

isFoo now is either true or false, regardless what foo contains, could be an Array, an integer, a string or even undefined. This can come in handy, if you want to check if a specific variable was passed into a function:

var myFunc = function(foo, bar) {
    var bar = !!bar;
    if( bar ) { /* ... */ }
};

You could say, well, I can do this without that !! thing. That is true, but you would have to explicitly make a typeof check against 'undefined' in this case.


  • The plus cast (+)
Sometimes, you want to have an integer value, even if you know that you are dealing with a string for instance. Most people would come up with the idea to call .parseInt() to convert that string into an integer. Among other things why .parseInt() is evil (lot's of people forgot to pass the radix value which decides which numeral system to use) it has a pretty "wrong" behavior. For instance:

var foo      = "55abc",
    mynumber = parseInt(foo, 10);

mynumber would contain 55. This is, for my understanding, pretty wrong. It should be NaN!
What can we do about it ? We use this:

var foo      = "55abc",
    mynumber = +foo;

Now, mynumber really is NaN. If foo would contain "55", the plus operator would cast it correctly into an integer. This can also be used on booleans. +true evaluates to 1, +false evaluates to 0.

2 comments:

  1. I've not seen `~~foo` used before, but if it works, great; however, what I have seen instead is `foo >> 0` for conversion to signed integer and `foo >>> 0` for conversion to unsigned integer; also, converting to string can be done via `'' + foo`

    ReplyDelete
  2. Brilliant! Especially the replacement for Math.round!

    ReplyDelete