What general tips do you have for golfing in JavaScript? I'm looking for ideas that can be applied to code golf problems in general that are at least somewhat specific to JavaScript (e.g. "remove comments" is not an answer).

Note: Also see Tips for Golfing in ECMAScript 6 and above

  • \$\begingroup\$ I was actually wondering, is it allowed to put variables in global (saves var)? And should JavaScript golf code be a function or output something directly? I honestly think this can make much difference. \$\endgroup\$
    – pimvdb
    May 27, 2011 at 5:28
  • 1
    \$\begingroup\$ @primvdb: It is allowed, but you have to be careful because it can cause side-effects if a function is called multiple times and it is manipulating global variables, or if it is a recursive function. \$\endgroup\$
    – mellamokb
    May 27, 2011 at 13:44
  • \$\begingroup\$ This link has a bunch of tips relevant here. \$\endgroup\$
    – Claudia
    Feb 12, 2015 at 4:53
  • \$\begingroup\$ I have discovered probably the most useless tip: a private class element doesn’t require a space before the private identifier in cases where it is preceded by a keyword: (class{static #x = 1;get #y(){};set #y(z){}}) can be rewritten as (class{static#x = 1;get#y(){};set#y(z){}}). This makes for some nice obfuscation, too, but I can’t think of a practical example in code golf. \$\endgroup\$ Nov 1, 2021 at 15:26

91 Answers 91


Return 1 for true, 0 for false as much as possible

This should be relatively self-explanatory.

function f(x){return x?(d(x),!1):!0}
function f(x){return x?(d(x),0):1}
function f(x){return !x&&d(x)&0}
if(f(v)){/* ... */}

// ES6 versions
let f=x=>x?(d(x),!1):!0
let f=x=>x?(d(x),0):1
let f=x=>!x&&d(x)&0
if(f(v)){/* ... */}
  • \$\begingroup\$ Don't get what's going on here but from your description +!!x is shorter and more concise. \$\endgroup\$ Nov 5, 2015 at 17:27

If returning void, see if it is shorter to return something useful. This is kinda language-agnostic here.

This isn't an easy apply-anywhere thing, either, though. Word of warning, make sure your parentheses are balanced.

In ES6, in this example, 6 bytes saved

let l=x=>console.log(m+x),x=1,a;l(a=f(x));l(a=g(a));l(h(a))
let l=x=>(console.log(m+x),x),x=1;l(h(l(g(l(f(x))))))

In ES5, it is only 1 byte saved

function l(x){console.log(m+x)}var x=1,a;l(a=f(x));l(a=g(a));l(h(a))
function l(x){console.log(m+x);return x}var x=1;l(h(l(g(l(f(x))))))
  • \$\begingroup\$ If you need to call a void-returning function repeatedly, it can be especially useful to return the function itself. For example, l=(x,y)=>c.lineTo(x,y);l(1,2);l(3,4);l(5,6);l(7,8) can be rephrased as l=(x,y)=>c.lineTo(x,y)||l;l(1,2)(3,4)(5,6)(7,8), saving 3 bytes. Example usage \$\endgroup\$ Nov 22, 2016 at 16:56

Use Bitwise as Logic Operators When Dealing With Booleans

a = 1 //although this would usually be a boolean expression
b = 0 //same

Then, use && lazy evaluation to make a chain of ampersands:


Saves 3 characters

  • \$\begingroup\$ You could use 0 and 1 instead of booleans. Again, semicolons are optional. \$\endgroup\$
    – mbomb007
    May 21, 2015 at 19:37
  • \$\begingroup\$ I know, these were just examples. Instead of true and false, there would most likely be expressions. I used variables to illustrate my point. \$\endgroup\$
    – Cyoce
    May 21, 2015 at 21:33

If you are ever in a situation where you have an array a and you need to get its last element as an array of itself, use Array#slice():

[a[a.length-1]]    // 15
a.slice(-1)        // 11
  • 4
    \$\begingroup\$ And, if you don't mind changing the original array, [a.pop()], at 9 characters. \$\endgroup\$ Sep 8, 2017 at 16:53

When stringifying dates, .toJSON saves 5 bytes over .toISOString. Apparently this was supported as far back as Firefox 4, but this answer is only the sixth on PPCG to mention it.


Shortening Promise Chains with async/await

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

async x=>await(await(x()).foo()).bar()

Example 2

async u=>/\0/.test(await(await fetch(u)).text()))

Removing something from a string

When you want to remove a certain substring from a string, split by that and join.

.replace(/h/g,'') // 17 bytes
.split`h`.join`` // 16 bytes
.replaceAll('h','') // 19 bytes

Sadly the ES2021 replaceAll is longer.


Convert ints to strings by adding an empty string

For example:





Adding [] works too


Array#concat() and the spread operator

This largely depends on the situation.

Combining multiple arrays.

Prefer the concat function unless cloning.

0 bytes saved


3 bytes wasted


3 bytes saved


6 bytes saved

// Concatenate array of arrays

Prefer using an already existing array to Array#concat().

Easy 4 bytes saved

  • \$\begingroup\$ Can't see the point of all this. Concat works with multiple array parameters, does not need apply or spread. Example 1: a.concat(b,c,d,e,f) \$\endgroup\$
    – edc65
    Feb 11, 2015 at 0:09
  • \$\begingroup\$ Flatten: let f=l=>[].concat.apply(l.map(x=>Array.isArray(x)?f(x):x)) vs let f=l=>[...l.map(x=>Array.isArray(x)?f(x):x)] \$\endgroup\$
    – Claudia
    Feb 11, 2015 at 1:56
  • \$\begingroup\$ Well...except my flatten shouldn't work. Here's a corrected version: let f=x=>[].concat(...l.map(x=>Array.isArray(x)?f(x):x)). The previous version would've done nothing. \$\endgroup\$
    – Claudia
    Feb 12, 2015 at 3:53
  • \$\begingroup\$ It's still 6 bytes saved. \$\endgroup\$
    – Claudia
    Feb 12, 2015 at 3:53

Adding Values with Implicit Casting

Improved zzzzBov solution:

//not so good

a- -b==c;

We save 2 characters by using these solutions.

  • \$\begingroup\$ +"10"+ +"5"===15 \$\endgroup\$
    – gion_13
    Mar 14, 2012 at 9:59
  • 2
    \$\begingroup\$ Note that the space is needed because the -- (decrement) operator takes precedence over subtraction. Also, @gion_13, what's the point? your solution has one extra character. \$\endgroup\$ Dec 18, 2012 at 13:18
  • 1
    \$\begingroup\$ You can replace the space with a + (e.g. a-+-b) \$\endgroup\$
    – Toothbrush
    Nov 5, 2015 at 16:37
  • 2
    \$\begingroup\$ In this case use a==c-b \$\endgroup\$
    – l4m2
    Apr 13, 2018 at 16:24


If you need a function in as few bytes as possible, and any function will do (perhaps you just want to access some of the goodies from Function.prototype), then here are some options (starting with large ones):

CSS     (available in modern browsers)
Map     (ES6: available in Node and modern browsers)
Set     (ES6: available in Node and modern browsers)
URL     (available in very old browsers, but not in Node)

So if you want a reference to the call function, you can get it like this:


If iterating through own properties, prefer Object.keys.

15 bytes saved

for(let p in o)if(o.hasOwnProperty(e)){/* ... */}
for(let p of Object.keys(o)){/* ... */}
Object.keys(o).map(p=>{/* ... */})

This is also the case for ES5, where it is 7 bytes saved.

for(var p in o)if(o.hasOwnProperty(e)){/* ... */}
Object.keys(o).map(function(p){/* ... */})

If you do that more than once, alias it as a function.

In this ES6 example, 6 bytes saved. It still saves bytes in ES5, but only if used 3 times or more.

Object.keys(o).map(p=>{/* ... */})Object.keys(o).map(p=>{/* ... */})
i=f=>Object.keys(o).map(f);i(p=>{/* ... */});i(p=>{/* ... */})

If you are using the same function more than once, it's often useful to reference the function to a new function name. I.e:

Instead of:


you can do:

  • 6
    \$\begingroup\$ Correct, but that is not JavaScript specific, is a generic tip added to Tips for golfing in <all languages> by Blazer more that 6 years ago. \$\endgroup\$
    – manatwork
    Jun 26, 2018 at 8:32
  • \$\begingroup\$ Welcome to PPCG! As manatwork pointed out this tip has already be posted, so I recommend deleting it. But I hope you nevertheless stick around and answer some challenges. :) \$\endgroup\$
    – Laikoni
    Jun 26, 2018 at 12:55
  • 2
    \$\begingroup\$ 4**.5;16**.5;100**.5 is even shorter. \$\endgroup\$
    – Dennis
    Jun 26, 2018 at 14:53
  • \$\begingroup\$ Thanks for your replies. I will take a look at the general tips. Maybe I find something which has not yet been added ;) love code golfing though! \$\endgroup\$
    – Xzibitee
    Jun 29, 2018 at 11:57

Square root hack

Use (x+2)**(1/2) instead of Math.sqrt(x+2).

  • 1
    \$\begingroup\$ a√b = a^(1/b) This can be applied to non-JavaScript languages. \$\endgroup\$
    – user85052
    Feb 1, 2020 at 3:20
  • 7
    \$\begingroup\$ Wouldn't it be shorter to use .5 instead of 1/2? \$\endgroup\$
    – Stephen
    Feb 1, 2020 at 5:17
  • 1
    \$\begingroup\$ .5 would be shorter, but this way, it applies to 3rd, 4rth, etc. \$\endgroup\$ Apr 23, 2020 at 20:03

Abusing template literals

You can often save two bytes on parentheses by replacing




This works for most properties that take in a single string.

This has been used in other answers, but there isn't an answer dedicated to this specifically.


If you need to do something different depending on several different values for a string, instead of:

}else if(v=='goodbye'){



When using regexps, if you need . to exclude \n, so you can't use the /s flag, you can uniquely (other regex engines do not allow this) write [^] instead of [\s\S] saving 3 bytes.


ES6-specific: avoid Function#bind()

Self-explanatory, 7 bytes saved


Use sloppy mode to avoid variable declarations

Here, 8 bytes saved

a.forEach(e=>{let b=e+1,c=d(b)+2;f(e);g(b);h(c);i(b,c)})

// Even better, reuse variables and use `Array#map()`
// Drops an additional 6 bytes

This also holds in ES5. Here, 8 bytes saved

a.forEach(function(e){let b=e+1,c=d(b)+2;f(e);g(b);h(c);i(b,c)})

// Even better, reuse variables and use `Array#map()`
  • 1
    \$\begingroup\$ 1. You don't ever need to initialize variables in code-golf unless you want them to be undefined, so getting rid of let saves 4 bytes off of the first line of both examples. 2. If you want to use .bind with customizable parameters, .bind is better: q=f.bind(0,x) vs. q=(..._)=>f(x,..._) (though if you only want one parameter, q=y=>f(x,y) is better). \$\endgroup\$ Dec 3, 2016 at 20:12
  • \$\begingroup\$ @ETHproductions Updated \$\endgroup\$
    – Claudia
    Dec 3, 2016 at 20:39

This is one of my favorites - ES6

 ["d", "a", ",", "d", "a", "d", ",", "s", "a"]

["da", "dad", "sa"]
  • 4
    \$\begingroup\$ The first one [...'asdasd'] \$\endgroup\$
    – l4m2
    Apr 25, 2018 at 6:34
  • \$\begingroup\$ Did you copy and paste ? it, if done in the console and in code pen I get ["d", "a", ",", "d", "a", "d", ",", "s", "a"] 'da,dad,sa'.split`` (9) ["d", "a", ",", "d", "a", "d", ",", "s", "a"] \$\endgroup\$ Apr 26, 2018 at 13:26
  • \$\begingroup\$ [...'da,dad,sa'] ... \$\endgroup\$
    – Cétia
    Jun 27, 2018 at 15:58

Use the simplest shortening method available - your variable declaration!

var myName = "Jack";

Obviously is very long compared to:


It's a whole 12 characters shorter. You have all 64 of these single-character variable names available:


And also - never use spaces or semicolons in your variable naming - changing m = "Mum"; to m="Mum" saves another three characters.


You can check if a value is *truish by simply passing it:


*everything different than 0, 0n, "", false, null, undefined and NaN is evaluated to true !

This method can be applied with many other functions and operators:

  • ternary operator val?"true":"false";
  • for loop for(;val;){...}
  • while loop while(val){...}
  • etc...
  • \$\begingroup\$ Or val&&.... Now, it is not equivalent to val == true. Example: 0 != true. \$\endgroup\$
    – Claudia
    Feb 12, 2015 at 4:56
  • \$\begingroup\$ All these strings also evaluate to true: '0', ' ', ' 0', '0 ' \$\endgroup\$
    – Toothbrush
    Nov 5, 2015 at 16:41
  • \$\begingroup\$ The technical term for "truish" is "truthy". \$\endgroup\$ Jun 24, 2020 at 3:43
  • \$\begingroup\$ Other falsy things: window.all and new Date("1970-01-01T00:00:00.000Z") \$\endgroup\$
    – mousetail
    Jul 20 at 14:29
  1. Checking if a string includes a character, e.g. 0:
if(~s.indexOf(0))    // -3
if(s.includes(0))    // -3
if(s.match(/0/))     // -4
if(/0/.exec(s))      // -5

exec is shorter than match.

  1. Ceiling a division:
(a+b-1)/b|0    // -3

Even shorter (if you don't mind editing a):

--a/b+1|0     // -5
-~(--a/b)     // -5 too
  1. String to array
// s is a string
[...s]        // -7
  • 1
    \$\begingroup\$ You can also use /0/.test(s) \$\endgroup\$
    – hypers
    Jun 17, 2021 at 9:05


sometimes you can use throw instead of alert to save 1 byte

throw !0

Do note that the program terminates, so you can't use it for loops.

  • \$\begingroup\$ You don't need the space in this instance: throw!0 \$\endgroup\$
    – pxeger
    Dec 19, 2021 at 21:19

Compressing Long Strings

If you have a very long, repetitive string, you can compress it using something similar to:


The `` should contain any code points between 0 and 127, with some needing to be escaped. These are: 0x00 (\0 or \x00, depending on whether a digit is following), 0x0d (\r), 0x5c (\\), and 0x60 (\`). In some very rare cases you may need to escape a $ if it is followed by a {.

You should replace n with the number of bits the output should be grouped into, and you can put any code you want in the final map and use +("0x"+p) to get the decimal value wherever necessary.

This adds roughly 100 bytes of overhead, compared to atob/btoa's 8. This method fits just under 7 bits per character in the string (due to escaping), and takes advantage of the fact that JS lets you put pretty much any code points into a string.

In order for this to be shorter, the data compressed needs to be one of:

  • Binary or numeric data, which is difficult to work with using atob and btoa
  • A string that has few distinct characters and is longer than 100 or so characters

In order to create a compressed string, convert each chunk of the string to binary using whatever encoding you want, then break it into chunks 7 bits wide. You may need to add some padding, which will be ignored if it is under 7 bits. Then, convert these into code points and paste them into the string.


For ES6 arrow functions with 2 parameters, nest functions


Only works in some cases. E.g. for recursive functions, this doesn't help because calling is one byte longer:


You can produce undefined with 0[0] to save 5 bytes. This is 2 bytes shorter than the more traditional void 0 method of creating undefined.

  • 3
    \$\begingroup\$ Note that you can also use [].x, or, if you have a variable defined anywhere in the program/function (which is very likely), something like x.x, a.x, _.x, and so on, which is a byte shorter. \$\endgroup\$ Nov 15, 2021 at 21:29

Remove duplicates from array

a.filter(e=>!(t[e]=e in t)) 

let unique= (a,t={})=> a.filter(e=>!(t[e]=e in t));

// "stand-alone" version working with global t:
// a1.filter((t={},e=>!(t[e]=e in t)));

// Test data
let a1 = [5,6,0,4,9,2,3,5,0,3,4,1,5,4,9];
let a2 = [[2, 17], [2, 17], [2, 17], [1, 12], [5, 9], [1, 12], [6, 2], [1, 12]];
let a3 = ['Mike', 'Adam','Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl'];

// Results
console.log(JSON.stringify( unique(a1) ))
console.log(JSON.stringify( unique(a2) ))
console.log(JSON.stringify( unique(a3) ))

O(n) performance; we assume your array is in a and t={}. Explanation here

And shorter but slower version (which not work with 2D arrays)

[...new Set(a)]

let unique = a => [...new Set(a)];

// Test data
let a1 = [5, 6, 0, 4, 9, 2, 3, 5, 0, 3, 4, 1, 5, 4, 9];
let a3 = ['Mike', 'Adam', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl'];

// Results

  • \$\begingroup\$ @manatwork So it is, I missed that when reviewing :/ \$\endgroup\$ Aug 22, 2019 at 9:50
  • \$\begingroup\$ You don't need a t, you can set properties of the array. only works with non-integers thoguh \$\endgroup\$
    – emanresu A
    May 9 at 10:45

I have adapted to my needs the Unicode shortcuts method by @bebe.

The problem which many have faced with the original solution is due to the fact that some of the functions/properties belong to a class prototype while others to a class itself. These need to be handled separately.

The minified code now takes 132 bytes:


Of course, you can drop Number and Array if unused from the initial array to save a couple of bytes. String is used in the code itself so removing it doesn't help a lot.

Part of the problems came from Math having no protype thus requiring its special handling. Besides the name in the initial array it also takes another 5 bytes to skip prototype handing. So use the variant below only if you need Math:


I use the same code for Node.js (v12.19.0) and Chrome (90.0.4430.212 x64).

Code Char Number          Number.prototype String        String.prototype  Array    Array.prototype Math
248  ø    length            constructor    length        length            length    length         abs
249  ù    name              toExponential  name          constructor       name      constructor    acos
250  ú    prototype         toFixed        prototype     anchor            prototype concat         acosh
251  û    isFinite          toPrecision    fromCharCode  big               isArray   copyWithin     asin
252  ü    isInteger         toString       fromCodePoint blink             from      fill           asinh
253  ý    isNaN             valueOf        raw           bold              of        find           atan
254  þ    isSafeInteger     toLocaleString               charAt                      findIndex      atanh
255  ÿ    parseFloat                                     charCodeAt                  lastIndexOf    atan2
256  Ā    parseInt                                       codePointAt                 pop            ceil
257  ā    MAX_VALUE                                      concat                      push           cbrt
258  Ă    MIN_VALUE                                      endsWith                    reverse        expm1
259  ă    NaN                                            fontcolor                   shift          clz32
260  Ą    NEGATIVE_INFINITY                              fontsize                    unshift        cos
261  ą    POSITIVE_INFINITY                              fixed                       slice          cosh
262  Ć    MAX_SAFE_INTEGER                               includes                    sort           exp
263  ć    MIN_SAFE_INTEGER                               indexOf                     splice         floor
264  Ĉ    EPSILON                                        italics                     includes       fround
265  ĉ                                                   lastIndexOf                 indexOf        hypot
266  Ċ                                                   link                        join           imul
267  ċ                                                   localeCompare               keys           log
268  Č                                                   match                       entries        log1p
269  č                                                   matchAll                    values         log2
270  Ď                                                   normalize                   forEach        log10
271  ď                                                   padEnd                      filter         max
272  Đ                                                   padStart                    flat           min
273  đ                                                   repeat                      flatMap        pow
274  Ē                                                   replace                     map            random
275  ē                                                   search                      every          round
276  Ĕ                                                   slice                       some           sign
277  ĕ                                                   small                       reduce         sin
278  Ė                                                   split                       reduceRight    sinh
279  ė                                                   strike                      toLocaleString sqrt
280  Ę                                                   sub                         toString       tan
281  ę                                                   substr                                     tanh
282  Ě                                                   substring                                  trunc
283  ě                                                   sup                                        E
284  Ĝ                                                   startsWith                                 LN10
285  ĝ                                                   toString                                   LN2
286  Ğ                                                   trim                                       LOG10E
287  ğ                                                   trimStart                                  LOG2E
288  Ġ                                                   trimLeft                                   PI
289  ġ                                                   trimEnd                                    SQRT1_2
290  Ģ                                                   trimRight                                  SQRT2
291  ģ                                                   toLocaleLowerCase
292  Ĥ                                                   toLocaleUpperCase
293  ĥ                                                   toLowerCase
294  Ħ                                                   toUpperCase
295  ħ                                                   valueOf
296  Ĩ                                                   replaceAll (*)


replaceAll (marked with an asterisk) exists only for Chrome.

Some comments where criticizing the usage of non-standard alphabet. If you manage to find another consistent range of Unicode characters that can be used as property names in JS then feel free to improve this answer. I couldn't find better than the original.


Add elements to Array

The concat is more useful than push in many situations because it returns whole array e.g. we want from d=[{a:1,b:2,c:3},{a:7,b:8,c:9}] generate 'pivot object' p={"a":[1,7],"b":[2,8],"c":[3,9]}

let p={}, d=[{a:1,b:2,c:3},{a:7,b:8,c:9}]; 

d.map(x=> Object.keys(x).map(k=> p[k]= (p[k]||[]).concat(x[k]) ))


  • 2
    \$\begingroup\$ Instead of mapping the keys, you can do for(k in x) and, instead of the concatenation, you can do p[k]=[...p[k]||[],x[k]]. After wrapping that in {}s, it saves you 14 bytes. TIO \$\endgroup\$
    – Shaggy
    Sep 17, 2019 at 9:37
  • \$\begingroup\$ @Shaggy thanks :) - I don't know that tricks. May be you have also some suggestion to this? \$\endgroup\$ Sep 17, 2019 at 10:10

The 9**999 is Infinity shortcut (2 characters shorter)

console.log( 9**999===Infinity )

  • 10
    \$\begingroup\$ 1/0 is a bit shorter \$\endgroup\$
    – James
    Feb 27, 2020 at 14:53
  • \$\begingroup\$ @James wow - it is not NaN (I don't know this) \$\endgroup\$ Feb 27, 2020 at 14:58

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.