Skip to content

General Javascript Golfing Tricks

Paul "Joey" Clark edited this page May 1, 2019 · 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()

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 3 or less? You can use for ... in

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

If you want to loop the values of a string:

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

Looping over a grid

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)

Statement separators

Usually in Javascript we use ; to separate statements. But when golfing, we can save space by using , or | to combine multiple expressions into one expression.

if(x){thing1();thing2()}
if(x)thing1(),thing2()

// Unfortunately commas won't help inside arrow functions
f=(a,b)=>thing1(a,b),thing2(b,a)     // will run thing2 _outside_ the function!

// But no problem.  In an arrow function, we can use | or & instead of ,

f=(a,b)=>{thing1(a,b);thing2(b,a)}
f=(a,b)=>thing1(a,b)|thing2(b,a)     // These both evaluate thing2()
f=(a,b)=>thing1(a,b)&thing2(b,a)     // regardless of the result of thing1()

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()

Shortening long function names

This is an experiment with mediocre results. It's probably more suitable for js1k.

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, we can use p(this,/XM/).

Some better alternatives:

If you want to call a long-named function twice:

x[f='fillRect'](... first call ...)
x[f](... second call ...)

Example: d/7330

Another trick, for really long property names, is to generate minimised names:

for(p in x)this[p[0]+p[6]]=p

This code adds two-letter string shortcuts to the global this, for all the functions in x:

this['fc']='fillRect'          // creates new global window.fc
this['gC']='globalComposite'   // created new global window.gC

That allows us to reference the real fillRect and globalComposite properties like this:

x[fc](...)
x[gC]='lighter'

and all the other properties of x too! Example: d/9134

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, an iterators loops a string different. So you can use an iterator to copy emojis into an array, without losing them:

[...'🐸🌷☁️️'].map(e=>console.log(e))

or

for(e of'🐸🌷☁️️')console.log(e)

Extreme Javascript Tricks

If you need to call a function many times, you can override the valueOf of an object, and trigger the interpreter to call it without having to use any ()s in your own code. (demo, slide)

// Before
r=Math.random;x.arc(r(),r(),r(),r(),r(),r())
// After
T.valueOf=Math.random;x.arc(T,T,T,T,T,T)

Explanation: When an object is used in an algebraic expression, before coercion its valueOf function is called by the interpreter.