

Byte-saving techniques in JavaScript - jedschmidt
https://github.com/jed/140bytes/wiki/Byte-saving-techniques

======
beaumartinez
"Byte-saving" made me think more of memory management than source file size.

Since version 1.5, JavaScript accepts Unicode characters as identifiers.
Shouldn't this be "character-saving"?

------
ricardobeat
I hope everyone is upvoting this just for science. DON'T use these all the
time, leave this job for a minifier and focus on maintainable code.

~~~
po
I think this is meant to be a fun project that gets people to learn some of
the quirks in the Javascript language. It reminds me a little bit of code
obfuscation contests: the more deeply you understand the language, the better
you will do. The advantage here is that it's not intentionally misleading and
actually could be useful.

~~~
jedschmidt
This is a good point. If you're going to write minified code like this, you
should at least annotate it liberally like this example:

<https://gist.github.com/962814>

------
dave1010uk
This is aimed at people writing tweet-sized JavaScript for <http://140byt.es/>
. This is a great resource for learning JavaScript and has some very
impressive code behind it. Generally for production sites, though, I'd much
rather go with jQuery due to its extensive test suite and bowser support.
Between tweet-sized and jQuery-sized JavaScript, there's a whole lot of micro
JS scripts / frameworks on <http://microjs.com/>

I'm currently writing a mobile web app that needs to work over GPRS
connections with 30kb/s bandwidth and up to 1s latency. In these cases,
shaving off a few bytes to get a page in 1 fewer TCP/IP packets really does
make a difference.

~~~
sh1mmer
Good lord, I'm pretty sure no-one is suggesting you use these in production.
In fact it says at the top you shouldn't.

If you are writing mobile apps you should check out XUI instead of jQuery.
jQuery (even jQ Mobile) is super heavy. XUI is jQ like, but it is by the
Nitobi guys (of PhoneGap fame) and they really get mobile and did it right.

~~~
jedschmidt
A lot of these tricks _are_ used in production, the result of uglifyjs/closure
minification of otherwise sane code. This is just a guide for hand-tuning.

------
binarymax
I love doing stuff like this for fun. Sometimes I try to get nice algorithms
into tweets. Here is one of my favorites so far, returns the powerset for
array 'a':

    
    
                function P(a){for(p=[],i=Math.pow(2,l=a.length);i;)for(b=i.toString(2),j=k=b.length,p[--i]=[];j;)if(b[--j]==1)p[i].push(a[j+l-k]);return p}
    

I know that there are some big gotchas here, such as b and p being declared
globally due to lack of var...but I gave up trying to gain an extra 4 bytes
for function(a,b,p). Also the subset arrays are in reverse order.

~~~
jedschmidt
There's a lot of room in there:

    
    
        Math.pow(2,l=a.length)
        1<<(l=a.length)
    

are the same, as are these:

    
    
        if(b[--j]==1)
        ~-b[--j]||

~~~
binarymax
Thanks! This is an amazing guide. I forsee many more lost hours shaving and
shaving with this in hand.

~~~
jedschmidt
Just remember to fork the master gist (<https://gist.github.com/962807>) when
you're done, and add an annotation so that the rest of us can learn from it!

------
leif

      rand10=Math.floor(Math.random())*10 // before
      rand10=0|Math.random()*10           // after
    

The first is not random, it will always return zero (this error is _very_
common). The second happens to be ok because * binds tighter than |. However,
this is order-dependent.

~~~
jedschmidt
Oops, that was an error (the multiplication should be within the .floor call).
It's fixed now.

This style of code, while not for everyone, exploits the "happens to be okay"
operator precedence. For this, Mozilla's MDC is a great resource:

[https://developer.mozilla.org/en/JavaScript/Reference/Operat...](https://developer.mozilla.org/en/JavaScript/Reference/Operators/Operator_Precedence)

------
orls
Hah. Wish I'd thought of some of these for last year's
<http://10k.aneventapart.com> .

I tried to write most of my JS for 10k 'pre-minified', using tricks akin to
(but not as awesome as) these. Echoing other commenters, it was largely as an
intellectual exercise (to see if I could meet the 10k limit by hand) but it
did make me think of a few things in a different light, and some of the
'optimizations' are things that minifiers wouldn't have done for me.

It's also a good way to get under the skin of a language, get a feel for the
nuances of how the runtime behaves, and give you hints for other (more
generally useful) optimisations.

~~~
jedschmidt
It's also interesting to see how the approaches differ at each order of
magnitude from 140byt.es to JS1K to 10K Apart.

At the smallest end you really have to work with what you're given and triage
fast, whereas with JS1K you see people writing decompressors _in_ their code
to get around JavaScript's occasional verbosity.

------
sktrdie
Shouldn't minifiers worry about all this stuff?

~~~
tlrobinson
Generally yes, but sometimes it's a fun intellectual challenge to squeeze a
piece of code as small as possible. Humans can also make assumptions that a
"safe" minifier can't.

------
simonsarris
They should also add:

    
    
        Math.floor(someNumber) // 2.6 becomes 2
        someNumber | 0         // 2.6 becomes 2
    

Not only because it saves characters, but because it might actually be used in
the real world (Whereas most of the ones in the article should really be left
to a minifier)

~~~
afshin
The problem with this technique is that it will not work for large numbers (in
my build of node, for example, the largest number it will work with is 2^31 -
1:

    
    
      (Math.pow(2, 31) - 0.1) // base number
        2147483647.9
      ~~(Math.pow(2, 31) - 0.1) // works!
        2147483647
      (Math.pow(2, 31) + 0.1) // base number
        2147483648.1
      ~~(Math.pow(2, 31) + 0.1) // doesn't work!
        -2147483648

