JS Code Golfing - How To Ruin Everyone's Day
Tags: javascript, codegolfing
Published: 2019-08-12 13:02:12

The title of this article is a little tongue-in-cheek. 
Code golfing is a term used to describe the practice of getting as few "points" (as you do in golf) as possible by using as little code as possible.

Javascript is a fantastic language for code golfing due to backwards compatibility, quirks, it being a high level language, and all the coercion. We're going to go over some extreme JS code golfing examples and explain how and why they work.

While extreme code golfing can quickly make your codebase an unreadable mess, occasionally certain aspects of code golfing can make some more complex-looking code much more readable. Understanding code golfing can also give you a better understanding of some concepts in JS.

# The Basics
Here we're going to go over some code golfing tricks that I'm sure you've seen before. This includes:
1. Shorten variable names.
2. Don't use intermediate variables for simple operations.
3. Avoid blocks when possible (if, while, and for statements).
4. Don't unnecessarily use `else` statements after a return.
5. Use arrow functions when possible.

Let's give a code snippet and then shorten it using these 5 basic rules.

```js
// 345 characters
function getNumOneOrZeroOff(baseNumber, shouldTryToGoUp, falsyOrTruthyVal) {
  const myBoolean = Boolean(falsyOrTruthyVal);
  const oneOrZero = Number(myBoolean);

  if (shouldTryToGoUp) {
    const numberPlus = baseNumber + oneOrZero;
    return numberPlus;
  } else {
    const numberPlus = baseNumber - oneOrZero;
    return numberPlus;
  }
}
```

Besides the fact that this is a pretty useless function, it's kind of unnecessarily long.

Let's implement the first 5 basic rules to shorten this up a bit.

```js 
// 164 characters
const getNewNum = (num, goUp, arbitraryVal) => {
  const oneOrZero = Number(Boolean(arbitraryVal));

  if (goUp) return num + oneOrZero;
  return num - oneOrZero;
}
```
>shortened variable names
>removed `const myBoolean = ;{}else{}`, whitespace, and lines 7,10

Wow, despite us removing a lot of the super specific variable names, it actually got way easier to read. Let's make this even shorter with 4 more basic rules.

1. Prefer unary `!!` instead of `Boolean()`.
2. Prefer unary `+` instead of `Number()`.
3. Prefer ternaries over `if` statements when possible.
4. Shorten ternaries to the delta of the 2 expressions.

```js 
// 136 characters
const getNewNum = (num, goUp, arbitraryVal) => {
  const oneOrZero = +!!arbitraryVal;

  return num + (goUp ? oneOrZero : -oneOrZero);
}
```
>removed `Number(Boolean())ifreturn;num` and whitspace
>added `+!!?:`

Number 4 might have been a bit confusing. What that means is instead of doing `return goUp ? num + oneOrZero : num - oneOrZero`, we do `return num + (goUp ? oneOrZero : -oneOrZero)` since they both share a common factor (`num`). The delta is the difference of the 2 expressions - the only thing changing. 

There is only a 3 character difference (in our case), but this stuff adds up and *can* improve readability. We could also remove the parens for an additional 2 characters less, but it would be difficult to read.

Let's stop caring about readability for now.

# Obfuscation by Brevity

Reusing the previous snippet, we can employ some more rules.

1. Remove unnecessary whitespace.
2. Remove unnecessary parens.
3. Remove unnecessary semi-colons
4. Use single character variables
5. Prefer `let` over `const`.

```js 
// 43 characters
let f=(a,b,c)=>{let d=+!!c;return a+(b?d:-d)}
```
>shortened variables names
>removed `constconst;()` and whitespace
>added `letlet`

Here is where all the talk about code golfing improving readability goes straight out the window. It's practically indecipherable. 

What if we stopped caring about performance as well? 

1. Prefer reevaluating expressions if it saves space
2. Prefer creating global variables over defining with `let`, `const`, or `var` (assuming the lack of "use strict")

```js
// 26 characters
f=(a,b,c)=>a+(b?+!!c:-!!c)
```
> removed `let{}returnletdd+` and whitespace
> added `!!c`

by placing the `+!!` inside our ternary, we were able to remove a variable assignment, thus allowing a one-line return. In arrow functions with only a body containing a return statement, we can remove the braces.

We were also able to use `-!!` instead of `-+!!` because unary negation exists.

So throwing out almost all readability and best practices, we have decreased a function from 345 characters, all the way down to 26 - less than 8% of its original size! Wow.

Let's go a bit further and uncover some not *as* often used JS tricks.

# Expression Evaluation

In a certain sense, all functions and assignments are expressions. Many times functions will return `undefined`, but it's still *something*. This gives us a lot of power to shorten our code.

Time to dive into some more snippets!
```js
// empty function
const myFunc = () => {};

myFunc()       // -> undefined
!!myFunc()     // -> false
4 + +!myFunc() // -> 5

// assignments as expressions
let a = 1;
let b = 1;
let c = 1;
c += b += a += 1;

a // -> 2
b // -> 3
c // -> 4

// 2 operations at once
let i = 0;
console.log(i++); // logs 0 and now i is 1
console.log(++i); // logs 2 and now i is 2
```

It should be noted that declarations do not return anything (not even undefined) and therefore are not expressions. You cannot log `let a = 3` or use it anywhere in an expression (but you can do `let a = b = c`).

With the knowledge that these are all expression-able (new word), let's involve an oft-forgotten piece of JS. The following is valid JS:

```js
// ignore this. Just initializations.
let a = 0, b = 0, myFunc = (num) => console.log(num);

let c = (a++, b+=a, myFunc(2), a+=b, b + a); // > 2
c // -> 3
```

What just happened here? This is behavior you might be familiar with if you've use C++. In JS, we can write comma separated expressions inside parentheses. The expressions are evaluated left-to-right and the right-most expression is then returned. 

In our case, we did a lot of things that we might have otherwise done on their own line.

When is this useful? Well it wouldn't be very useful in most circumstances, since we could just ditch the parens and use semicolons instead. The most useful place is in `while` loops, `for` loops, and shortening arrow functions.

```js
// prints 0-9 inclusive
let i = 0;
while (console.log(i++), i < 10);

// prints 0-9 inclusive
for (j = 0; console.log(j++), j < 10;);

// 32 characters
a=>{r=0;a.map(n=>r+=n);return r}
// 25 characters
a=>(r=0,a.map(n=>r+=n),r)
// a reduce would do the same thing and be only 23 characters, I know
```

By the loops, we don't even need the parens; they're optional. We have created fully functional for and while loops with no body. Make sure to use a semicolon so that the loops don't accidentally loop some random statement right below it.

It should be noted that we're also able to leave out parts of a for loop as long as the parens of the for loop contain 2 semicolons. Due to our expressions, the last section of the parens (after the 2nd semicolon) is essentially useless as long as our last expression is a boolean (or evaluates/coerces to one).

We can also use turn non-expressions into expressions using the evil `eval()`. It's generally recommended to avoid it, but there are some use cases, such as code golfing. It always returns the last expression, so we can use it to decrease an arrow function by 3 characters. We're saving pennies at this point, but it might be worth it in the long term.

```js
// 43 characters
a=>{for(var o="",i=0;i<a;i++)o+=i;return o}

// 40 characters
a=>eval('for(let o="",i=0;i<a;i++)o+=i')
```


# Taking Advantage
There are a lot of tricky and quirky parts of JS which reveal some pretty interesting behaviors. We can take advantage of these behaviors to shorten our code.

The more common of these tricks is using [bitwise operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators) to coerce floating point numbers into integers. Usually we would use something like `Math.floor()`, `Math.ceil()`, or `Math.round()`, but these take up far too many characters. 

We can use bitwise operators, which have a side effect of truncating decimals, to perform a *similar* behavior with only 2 characters. By using `~~` or `|0` we can perform bitwise operations that don't do anything. Since they truncate when calculating the result, we get a number without decimals. 

```js
// 31 characters
Math.floor(Math.random() * 100)

// 21 characters
~~(Math.random()*100)

// 19 characters
Math.random()*100|0
```
2 things to note: 1. truncation will get different results than `Math.floor()` when dealing with negative numbers. 2. bitwise operators are performed in the same order-level as multiplication. Think PEMDAS, but stick a B next to the M or D. This is why the second bitwise example didn't need parens, but the first did.
<br/>

Another behavior which you may be familiar with is [short circuit evaluation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Short-circuit_evaluation). It deals with the `&&` and `||` operators and allows us to save a lot of space. 

```js
// logs thing and then returns it
const logIt = thing => (console.log(thing), thing)

logIt(0) || logIt('hey') // logs both since 0 is falsy
logIt('hey') || logIt(0) // only logs 'hey' since 'hey' is truthy

logIt('hey') && logIt(0) // logs both since 'hey' is truthy
logIt(0) && logIt('hey') // only logs 0 since 0 is falsy
```
It's used many times to execute one or both functions depending on the return value of the first. If you want the second one to execute only if the function is truthy, use `&&`. If you want the second one to execute only if the function is falsy, use `||`. 

`&&` and `||` can also be used to retrieve the falsy or truthy value.
```js
const theFalsyOne = '' && 100; // it is ''
const theTruthyOne = '' || 100; // it is 100
```
If both are truthy, `&&` will return the second value and `||` will return the first one. If both are falsy, `&&` will return the first value and `||` will return the second. This behavior is due to short circuit evaluation as well.
<br/>

The last behavior surrounds `valueOf`. There was an interesting question about if [(a==1 && a==2 && a==3) can ever evaluate to `true`](https://codeburst.io/javascript-can-a-1-a-2-a-3-ever-evaluate-to-true-aca13ff4462d) and the answer had to do with `valueOf` as well.

We can create objects that appear to be primitive values when used in concatenation and mathematics. If we use an object in those circumstances, JS will check out its `valueOf` property to coerce it into a primitive. We can do some really cool stuff with this, but I've found the most common use to be for `Math.random()`

```js
const makeEllipse = (x, y, width, height) => { 
  // do stuff
}

// 91 characters
makeEllipse(Math.random() * 50, Math.random() * 50, Math.random() * 10, Math.random() * 10)

// 60 characters
let r={valueOf:Math.random}
makeEllipse(r*50,r*50,r*10,r*10)
```
There is obviously a trade-off when you have to define a new object and include the original function, but if you're using it enough, it helps to shorten it.

# Saving Pennies
In real code golf competitions, every character counts. If you can shave off a single character, do it. Here are some techniques to spare characters here and there.

Concatenate with `${}` instead of `++` when in between 2 strings. This saves a single character.
```js
// 27 characters
'You are '+age+' years old'

// 26 characters
`You are ${age} years old`
```

You can use regular functions as [tagged template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates) as long as the function uses the string it asks for as a string. This can save 2 characters.
```js
// 16 characters
myArr.split('.')

// 14 characters
myArr.split`.` 
```
This cannot work with things like `eval` since they don't use the input as if it were a string. You must also try to not include any `${}` since tagged template literals receive the variables in different parameters. 

If you have an infinite loop, use `for(;;i++)` over `while(true)i++`. This saves 4 characters. `i++` in this case is the expression or function which gets called every iteration.

Lastly, Numbers can also get called using scientific notation. Instead of `1000`, you can use `1e3` which will evaluate to the same thing. This saves one character starting at 1000, but the ROI quickly goes up with larger numbers.

#Closing Remarks
Code golfing can be a lot of fun. The practice can also teach you a lot about the language. 

I obviously could not cover all the JS code golfing tricks, but I hope I covered a decent chunk. I highly recommend checking out [this thread](https://codegolf.stackexchange.com/questions/37624/tips-for-golfing-in-ecmascript-6-and-above) for some more JS code golfing tricks.

If you want to start code golfing, I highly recommend checking out https://codegolf.tk/ and https://www.dwitter.net/
Those are sites which use code golfing and canvas to create beautiful visualizations with an absurdly minimal amount of characters.

Confused? Have some more tips to share? Feel free to leave a comment and let me know!