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 - , 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.



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)     // после


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.


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);         // после


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      // после


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>" // до                   // после

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")        // после


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


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.

Also popular now: