Code Compression Techniques

Published on May 24, 2011

Code Compression Techniques

Original author: Jed Schmidt
  • Transfer
Jed Schmidt, Thomas Fuchs and Dustin Diaz - guys quite well-known in the JavaScript community recently found a new amusement - writing useful things no larger than one tweet, i.e. 140 bytes. They even registered a domain - 140byt.es , where everyone is invited to try their hand at writing super-compact functions.

Naturally, all the most sophisticated methods and techniques for reducing the size of the source are used. They have a wiki page with tips, which I decided to translate.

I must say right away that the readability of the code processed in this way tends to zero, so it’s worth using these tricks only in cases when the size is really above all. For example, when participating in the JS1k contest.

So.

Arguments


Use single-letter positional arguments in alphabetical order


Since function arguments should be as short as possible, and most likely to be used several times at run time, it is easier to consider them in terms of position and name them in alphabetical order, rather than trying to give them any meaningful names.
function(t,d,v,i,f){...} // до
function(a,b,c,d,e){...} // после


Check for arguments instead of length


Can be used into check for an argument.
arguments.length>1||(cb=alert) // до
1 in arguments||(cb=alert)     // после


Variables


Use "extra" arguments instead var


You can save a few bytes by specifying an extra argument in the function, instead of declaring a variable with var:
function(a){var b=1;...} // до
function(a,b){b=1;...}   // после


Use variables several times


setTimeout(function(){for(var i=10;i--;)... }, a) // до
setTimeout(function(){for(a=10;a--;)... }, a)     // после


Use Assignment Where Possible


Since the assignment operator returns the assigned value, you can use assignment and validation at the same time:
a=this.localStorage;if(a){...} // до
if(a=this.localStorage){...}   // после


Use an array to swap variables


The array can be used as temporary storage, so as not to declare an extra variable.
var a=1,b=2,c;c=a;a=b;b=c // до
var a=1,b=2;a=[b,b=a][0]  // после


Use casting when adding


Type conversion in JS works very strange and is one of the most common source of bugs. However, it can be used in various interesting ways to reduce code size.
For example, in a pubsub implementation , Jed Schmidt decremented a variable with a negative number, and then added it to the string, getting something of the kind "somestring-123".
After that, in another place I used .split('-')to get the source string.

Cycles


Lower the body of the loop


Often, you can implement all the logic inside the conditions and save on the body of the cycle.
A good example of this approach can be seen in the timeAgo function .

Use for instead of while


forand whileusually occupy the same amount of bytes, but forallows you to get more control and more opportunities for assignment.
while(i--){...} // до
for(;i--;){...} // после
i=10;while(i--){...} // до
for(i=10;i--;){...}  // после


Use fast iteration over “true” arrays


If you have an array whose members are all known to be true, you can use a shorter loop entry:
for(a=[1,2,3,4,5],l=a.length,i=0;i<l;i++){b=a[i];...} // до
for(a=[1,2,3,4,5],i=0;b=a[i++];){...}                 // после


Use for..inwith assignment to get object keys


a=[];for(b in window)a.push(window[b]) // до
a=[];i=0;for(a[i++]in window);         // после


Operators


Learn operator priority


This knowledge can help save a lot on brackets.
You can start by exploring this article on the Mozilla website.

Use ~cindexOf


hasAnF="This sentence has an f.".indexOf("f")>=0 // до
hasAnF=~"This sentence has an f.".indexOf("f")   // после


Use a comma to execute statements sequentially instead of a block


with(document){open();write("hello");close()} // до
with(document)open(),write("hello"),close()   // после


Use shorter recording methods undefined


Instead, undefinedyou can use []._or void 0.
There are options ""._, 1.._and [][0], but they are much slower .

Remove optional spaces before operators


Sometimes spaces after operators can be removed painlessly.
typeof [] // до
typeof[]  // после


The numbers


Use ~~or 0|insteadMath.floor


rand10=Math.floor(Math.random()*10) // до
rand10=0|Math.random()*10           // после


Use exponential format for large round numbers


million=1000000 // до
million=1e6     // после


Use bit shifts for large binary numbers


color=0x100000 // до
color=1<<20    // после


Use 1/0insteadInfinity


It is shorter. In addition, dividing by zero is always fun.
[Infinity,-Infinity] // до
[1/0,-1/0]           // после


Use the falsity of zero


Instead of comparing numbers, it is sometimes shorter to reduce the value to zero and check its truth.
a==1||console.log("not one") // до
~-a&&console.log("not one")  // после


Use ~to change any value to one.


In combination with the unary minus, this makes it possible, for example, to increment any variable that has not yet been defined.
// i = undefined
i=i||0;i++ // до
i=-~i      // после


Lines


Break lines with zero


You can save two bytes when splitting strings by the method split, if you use zero as a separator:
'alpha,bravo,charlie'.split(',') // до
'alpha0bravo0charlie'.split(0)   // после


Use browser method link


Lines in browsers have a not-so-well-known method linkthat creates an html link.
html="<a href='"+url+"'>"+text+"</a>" // до
html=text.link(url)                   // после


Use replaceand methods execto iterate through the lines


These methods allow you to pass a function as the second argument. This can be used for convenient iteration over the line.
Examples of use: templates and UUID .

Use arrays to create simple strings.


for(a="",i=32;i--;)a+=0 // до
a=Array(33).join(0)     // после


Regular expressions


Use {n}to shorten regular expressions. For example, /\d{3}/instead of /\d\d\d/. And vice versa /\d\d/instead /\d{2}/.

Can be used evalinstead of the regular constructor constructor:
r=new RegExp("{"+p+"}","g") // до
r=eval("/{"+p+"}/g")        // после


Boolean


Use !with numbers to create trueand false.
[true,false] // до
[!0,!1]      // после


Functions


Use named functions for recursion instead of loops


This is often shorter, because it allows you to drag values ​​through the stack, without unnecessary variables.
As an example, the walk function .

Use named functions to store state


If you need to store the state between function calls, you can use the function as an object and store data in its properties:
function(i){return function(){console.log("called "+(++i)+" times")}}(0) // до
(function a(){console.log("called "+(a.i=-~a.i)+" times")})              // после
0,function a(){console.log("called "+(a.i=-~a.i)+" times")}              // еще вариант


Omit brackets when calling constructor without arguments


now = +new Date() // до
now = +new Date   // после


Omit the new keyword where possible


Some designers do not necessarily have a keyword new.
r=new Regexp(".",g) // до
r=Regexp(".",g)     // после
l=new Function("x","console.log(x)") // до
l=Function("x","console.log(x)")     // после


Return statement


When you need to return something other than a variable, putting a space after is returnnot necessary.
return ['foo',42,'bar']; // до
return['foo',42,'bar'];  // после
return {x:42,y:417}; // до
return{x:42,y:417};  // после
return .01; // до
return.01;  // после


That's all for now.

In general, I recommend that you familiarize yourself with the fruits of their work. In attempts to fit complex things into 140 bytes, guys sometimes just work wonders. I think even an experienced programmer will find something new and interesting in their code.