Having gotten hooked on it during the first js1k, written about extreme JS minification and submitted a bunch of stuff to 140bytes, I think it's fairly safe to say I'm an addict. Because of that, there was really no chance that I could let this year's js1k go by without entering.
There's not a lot I can say about minification techniques that hasn't already been covered either on this site, on Marijn Haverbeke's site, on Ben Alman's or on the 140bytes wiki page on byte-saving techniques. The only things I will add are a couple of techniques which are new to me. I have thoroughly commented the code below, however. If you want to play along, have a look.
It's a feature of most programming languages that when you have a logical operator such as
||, the value of the left side of the operator determines whether the right side will be evaluated at all. If the left side of an AND is false, we're going to get a false for the whole thing. It doesn't matter what the right side is so we don't even need to look at it. Similarly, if the left side of an OR is true, the eventual return value will be true so we don't need to look at the right. For example, here are two statements:
In the first example (
&& – AND), we will only check
coffee is true. We first have a look at
coffee and if it is false, we don't care whether morning is true or not, we just skip it (and, presumably, go back to bed). If
true, we'll then have a look to see if morning is true. It doesn't matter if morning is a function or a variable assignment or whatever, it will only happen if
coffee is true.
In the second example (
|| – OR), we will only evaluate
wine is false. We start by looking at and evaluating
wine. If that is true, the JS interpreter saves us from even considering
work and skips it. The right-side of the operator,
work, is only considered if wine is false.
You can probably see how, in a few simple situations, this can help avoid an
if(), thereby saving at least one byte. Usually.
If you want to set the font-size on a canvas 2D context, you have to use the font property. Makes sense, right? Unfortunately for obsessive minifiers, you can't just set the fontSize, you also have to set the fontFamily at the same time:
Failure to set the font family means that the whole value is invalid and the font size isn't applied.
My thought process: “But 'Arial'? The word's so… big (5 bytes). There must be some way to make this smaller. If only there were a font called ‘A’ (1 byte)…”
Well, it turns out, if you set a font that doesn't exist on the user's system, the canvas will fall back on the system sans-serif by default. On windows that is... Arial. On OS X, it's Helvetica. I'm glad about that because otherwise, Helvetica wouldn't get a look-in, being 9 whole bytes.
There is always the chance that someone will have a font called ‘A’ but I'm willing to take that risk. This possibility could be avoided by using an unlikely character like ♥ for the font name.
These are hosted on GitHub rather than in my usual code blocks to make it easier for you to fork them, pull them apart and get elbow-deep in them.
The almost-impossible-to-read minified submission:
The full, unminified code with thorough commenting:
My entry is up on the js1k site now. It's already getting quite busy up there after only a few days and I have to say I'm impressed by the fantastic job @kuvos has done in building it up over the last couple of years and providing me with fuel for my addiction.