Skip to content

General Javascript Golfing Tricks

Joey Clark edited this page Jun 5, 2018 · 15 revisions

Looping

A reverse for loop is shorter than a forwards for loop:

for(i=0;i<10;i++)...   // before
for(i=10;i--;)...

A for loop can use a , instead of {} to do multiple things inside the body:

for(i=10;i--;){thing1();thing2()}   // before
for(i=10;i--;)thing1(),thing2()

That trick works inside ifs too, but it does not work in the "body" of an arrow function, because that is an expression, not a statement.

You can save a further char by moving the last thing (or more) inside the for:

for(i=10;i--;)thing1(),thing2()   // before
for(i=10;i--;thing2())thing1()

Do you need to loop from 0 to 2 or less? You can use for ... in

for(i=0;i<3;i++)...
// becomes
for(i in 'omg')...
// but looping backwards is still shorter (if you can)
for(i=3;i--;)...

If you want to loop the values of a string:

for(p of '🦡🍄🐍')console.log(p)

Instead of two nested loops, you can often use one loop, and get the original numbers using floored division and modulus:

// Before
for(i=128;i--;)for(j=32;j--)draw(i,j)
// After
for(k=4096;i--;)draw(k/32|0,k%32)

And if the inner loop happens to be a power of two (such as 32 === 2**5), then you can get the flooring for free by using a bitshift for division:

// After
for(k=4096;i--;)draw(k>>5,k&31)

Dictionaries (hashtables)

You can use just about any existing Javascript object as a dictionary if you need to, to avoid initialising your own.

onclick=e=>{a=[],a[9]=5}
onclick=e=>{e[9]=5,a=e}

A dictionary can be used as a cheap array, but it won't give you .length or any Array methods.

With

Four times x. can be shortened using with(x)...

Need to call a function multiple times, but it's a member of another object?

You can't do F=x.fillRect;F();F() because F won't see its context object x.

But you can do:

x.F=x.fillRect;x.F(X,Y+7,3,3);x.F(187,Y+C(X/39)*29,5,20);x.F(0,Y-S(X/29)*22,5,20)

Alternatively, or additionally, try using the with operator.

with(x)F(),F(),F(),F()

You can even use multiple contexts:

with(Math,x)F(),F(),F(min(a,b))

Experiment

Some of the Javascript API functions have really long names. If you are using more than ~5 of these, then these functions might help. They let us search for properties using a regexp.

/** p(object, regexp) = find key in object */
p=(o,r)=>{for(k in o)if(k.match(r))return ok}
/** P(object, regexp) = get property from object */
P=(o,r)=>o[p(r)]

f=(o,r)=>p(o,r).bind(o)

If I am using the same o repeatedly, then I might remove the o argument from those functions, and instead set it as a global before calling p or P.

So now, instead of XMLHttpRequest ......................... ?

Logic

You can not do foo&&bar=1 but you can do foo?bar=1:0

Remember that | is greedy but % is not. Other bitwise operations are also greedy (&, <<, >>, ^).

If you need to floor and then modulus, instead of (x|0)%y you can use ~~x%y

Emojis

You can access most Unicode chars directly from a string: "abc"[k]

But that doesn't work so well with emojis, because emojis are two characters each, so you only get half the code!

However, you can copy emojis into an array, and extract from that: [...'🐸🌷☁️️'][k]

This only saves space if you are using 3 or more emojis.