Code Compression Techniques
- 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.
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.
Can be used
Use "extra" arguments instead
You can save a few bytes by specifying an extra argument in the function, instead of declaring a variable with
Since the assignment operator returns the assigned value, you can use assignment and validation at the same time:
The array can be used as temporary storage, so as not to declare an extra variable.
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
After that, in another place I used
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 .
If you have an array whose members are all known to be true, you can use a shorter loop entry:
Use
This knowledge can help save a lot on brackets.
You can start by exploring this article on the Mozilla website.
Use
Use shorter recording methods
Instead,
There are options
Sometimes spaces after operators can be removed painlessly.
Use
Use
It is shorter. In addition, dividing by zero is always fun.
Instead of comparing numbers, it is sometimes shorter to reduce the value to zero and check its truth.
Use
In combination with the unary minus, this makes it possible, for example, to increment any variable that has not yet been defined.
You can save two bytes when splitting strings by the method
Use browser method
Lines in browsers have a not-so-well-known method
Use
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
Can be used
Use
This is often shorter, because it allows you to drag values through the stack, without unnecessary variables.
As an example, the walk function .
If you need to store the state between function calls, you can use the function as an object and store data in its properties:
Some designers do not necessarily have a keyword
When you need to return something other than a variable, putting a space after is
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.
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
in
to check for an argument.arguments.length>1||(cb=alert) // до1inarguments||(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
for
and while
usually occupy the same amount of bytes, but for
allows 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..in
with assignment to get object keys
a=[];for(b inwindow)a.push(window[b]) // до
a=[];i=0;for(a[i++]inwindow); // после
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,
undefined
you 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/0
insteadInfinity
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
link
that creates an html link.html="<a href='"+url+"'>"+text+"</a>"// до
html=text.link(url) // после
Use replace
and methods exec
to 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
eval
instead of the regular constructor constructor:r=newRegExp("{"+p+"}","g") // до
r=eval("/{"+p+"}/g") // после
Boolean
Use
!
with numbers to create true
and 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){returnfunction(){console.log("called "+(++i)+" times")}}(0) // до
(functiona(){console.log("called "+(a.i=-~a.i)+" times")}) // после0,functiona(){console.log("called "+(a.i=-~a.i)+" times")} // еще вариант
Omit brackets when calling constructor without arguments
now = +newDate() // до
now = +newDate// после
Omit the new keyword where possible
Some designers do not necessarily have a keyword
new
.r=new Regexp(".",g) // до
r=Regexp(".",g) // после
l=newFunction("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
return
not 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.