88
\$\begingroup\$

This is similar to other "Tips for golfing in <...>" but specifically targeting the newer features in JavaScript brought up in ECMAScript 6 and above.

JavaScript inherently is a very verbose language, function(){}, .forEach(), converting string to array, array-like object to array, etc, etc are super bloats and not healthy for Golfing.

ES6+, on the other hand, has some super handy features and reduced footprint. x=>y, [...x], etc. are just some of the examples.

Please post some nice tricks that can help shave off those few extra bytes from your code.

NOTE: Tricks for ES5 are already available in Tips for golfing in JavaScript; answers to this thread should focus on tricks only available in ES6 and other future ES versions.

However, this thread is also for users who currently golf using ES5 features. Answers may also contain tips to help them understand and map ES6 features to their style of ES5 coding.

\$\endgroup\$

37 Answers 37

3
\$\begingroup\$

Splitting Strings

Surprised this hasn't been posted already (or maybe I missed it).

If you have an array of 5 or more strings, you can save bytes by instead splitting a string containing all the elements.

["one","two","three","four"]
"one,two,three,four".split`,` // 1 byte longer

["one","two","three","four","five"]
"one,two,three,four,five".split`,` // 1 byte shorter

["one","two","three","four","five","six"]
"one,two,three,four,five,six".split`,` // 3 bytes shorter

For each additional string in your array, you'll save a further 2 bytes with this approach.

If any of your strings contain a comma then change the delimiter to a differet character.

\$\endgroup\$
3
\$\begingroup\$

Using .padEnd() instead of .repeat() (ES8)

Under certain circumstances, using .padEnd() instead of .repeat() saves bytes.

We can take advantage of the following properties:

  • the default padding string is a single space
  • when provided, the second parameter is implicitly coerced to a string

Repeating spaces

With .repeat():

' '.repeat(10)

Using .padEnd() saves 1 byte:

''.padEnd(10)

Try it online!

Repeating a dynamic value that needs to be coerced to a string

With .repeat():

x=1;
(x+'').repeat(10)

Using .padEnd() saves 2 bytes:

x=1;
''.padEnd(10,x)

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Use ** (ES7)

** is the new exponentiation operator. Occasionally useful.

Math.pow(2,2) // size: 13, result: 4 
2**2          // size:  4, result: 4
\$\endgroup\$
  • \$\begingroup\$ This does work for me, tested in Chrome 58 on Linux. Kind of obvious as it's being reported in 2017 and ES6/7 have settled down now, but just to verify. \$\endgroup\$ – i336_ Aug 23 '17 at 0:06
  • \$\begingroup\$ @Satoshi, when raising a single digit number or a variable with a single character name to the power of 2, it's shorter to just multiply it by itself (e.g., 3*3 or n*n); the exponentiation operator only works out shorter when raising to the power of 3, or higher. \$\endgroup\$ – Shaggy Oct 17 '18 at 13:34
1
\$\begingroup\$

Aliasing using eval and template strings

This one's more effective with longer code containing more repetition:

a.push([0,1,2,3,4,5,6,7,8,9,10].push([0,1,2,3,4,5,6,7,8,9,10].push([0,1,2,3,4,5,6,7,8,9,10]))) // before
a.push([...Array(11).keys()].push([...Array(11).keys()].push([...Array(11).keys()]))) // before - golfed
a.push((f=_=>[...Array(11).keys()])().push(f().push(f()))) // before - golfed more

eval(`a${b=`.push([...Array(11).keys()]`}${b+b})))`) // after

Probably not the best example, but you get the idea.

Although the use case is somewhat limited, it can save quite some bytes, especially because it can get at several char sequences (like [function]([args]) or [...) that would otherwise be unable to be aliased.

Be careful with this, however; very often, using this technique can actually increase, not decrease, your byte count.

\$\endgroup\$
  • \$\begingroup\$ It's actually shorter just to do: a=>[...a[b='toLowerCase']()].map(x=>x[b]())[b](). Shouldn't this go under the regular Tips for Golfing in JS? \$\endgroup\$ – Downgoat Jan 28 '16 at 2:19
  • \$\begingroup\$ Perhaps that was a bad example. But the main reason this should go here is because using ${...} is the only way this stays golfy without losing its usefulness. \$\endgroup\$ – Mama Fun Roll Jan 28 '16 at 3:24
  • \$\begingroup\$ I'm coming up with a better example. \$\endgroup\$ – Mama Fun Roll Jan 28 '16 at 3:24
1
\$\begingroup\$

Convert BigInt back to Number (Chrome 67+ / Node.js 10.4+)

!! ALERT : ESNext feature ahead !!

BigInt makes arbitrary-precision integer arithmetic more handy in JS, but there is a caveat - most already existing functions that accepts Number, does not accept BigInt. UPDATE: array indexer DOES support BigInt for some reason.

When we need to convert a BigInt back to Number for some reason, we cannot use +n (this is explicitly forbidden in the specs), but instead we need to use Number(n) -- except we do not really need to do so.

Instead of using Number(n), we realise that we can actually convert the BigInt first into a String and then to a Number using +`${n}`, which saves 2 bytes.

But we can do better: wrap the BigInt with an array then directly cast it using + operator. This gives +[n] which saves 3 more bytes. Most importantly this eliminates the use of Number(n) or even (N=Number)(n) and further N(n)s for multiple uses because +[n] has the same length as N(n).

You can test this out with this example:

s=163n;
console.log(Number(s)) // 9 bytes
console.log(+`${s}`)   // 7 bytes
console.log(+[s])      // 4 bytes

Try it online!

\$\endgroup\$
0
\$\begingroup\$

(strawman) Use do expressions instead of evaling strings

[Babel preset] and [proposal].

Comes with the added bonus of keeping syntax highlighting. This might be a stretch in some contests, but is nonetheless interesting. I think if it's supported in Babel, it should qualify as competing.

Consider the following function (37 bytes):

f=n=>{for(o=i=0;i<n;o+=++i);return o}

This might be golfed down with the classic eval trick (34 bytes (thank you everyone)):

f=n=>eval("for(o=i=0;i<n;)o+=++i")

But we can do better with do (30 bytes):

f=n=>do{for(o=i=0;i<n;)o+=++i}

Working example - note that Babel needs let statements in all above functions as well.

Essentially what I'm trying to say is if a solution can be done with eval, you can almost always shave off a few bytes using do.

\$\endgroup\$
  • \$\begingroup\$ 35 bytes f=n=>eval("for(o=i=0;i<n;)o+=++i") \$\endgroup\$ – Yay295 Aug 16 '16 at 18:41
  • \$\begingroup\$ @Yay295 Incredible! Updated my post, thank you! \$\endgroup\$ – Scott Aug 16 '16 at 18:50
  • \$\begingroup\$ You can golf both of the first two functions down by 5 bytes by replacing f=(n,o=0)=>...i=0; with f=n=>...o=i=0; \$\endgroup\$ – ETHproductions Sep 13 '16 at 17:45
  • \$\begingroup\$ @ETHproductions Good point, I should have reflected those changes in the other examples when I updated the third. Thank you! \$\endgroup\$ – Scott Sep 13 '16 at 18:26
  • \$\begingroup\$ Briefly what is Babel? \$\endgroup\$ – edc65 Sep 13 '16 at 18:31
0
\$\begingroup\$

Shortening Promise Chains with async/await

Taken from my answer here.

Sometimes you can shorten longer promise chains with async/await. The main benefit is from getting rid of the beginning of the arrow function in each then callback. .then(x=>x (10) gets replaced with await( (-4), but you first pay with async (+6). So to make up for the initial overhead of 6 bytes, you'd need at least two then chains to get any benefit.

+-------------+----------------+
| then chains | async overhead |
+-------------+----------------+
| 0           | +6             |
| 1           | +2             |
| 2           | -2             |
| 3           | -4             |
| …           | …              |
+-------------+----------------+

Example 1

x=>x().then(y=>y.foo()).then(z=>z.bar())
async x=>await(await(x()).foo()).bar()

Example 2

u=>fetch(u).then(r=>r.text()).then(t=>/\0/.test(t))
async u=>/\0/.test(await(await fetch(u)).text()))
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.