Tips for golfing in JavaScript

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

• 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. – pimvdb May 27 '11 at 5:28
• @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. – mellamokb May 27 '11 at 13:44
• This link has a bunch of tips relevant here. – Isiah Meadows Feb 12 '15 at 4:53

Transforming to a Boolean:

if(b){b=true}else{b=false}
b=b?true:false;
b=b?!0:!1;
b=!!b;


Note: This changes 0, "",false, null, undefined and NaN to false (everything else to true)

2 to a power

If for some reason you need to calculate 2 to the nth power,

1<<n is shorter than Math.pow(2,n).

If you needed to calculate 2 to the n+1th power,

2<<n is even shorter than 1<<n+1

Likewise for 4<<n for n+2, 8<<n for n+3, 16<<n for n+4, etc.

(sorry if this is too obvious)

• and 2**nin ES6 – Cétia Jun 27 '18 at 7:57
• @Cétia That’s ES7. – user42589 Jan 16 '19 at 22:13

for a given array, we know a for..in loop might lead to errors because stuff might be added to the Array.Prototype, so we revert to a normal for loop:

for (var i=0; i<arr.length; i++ )


lets do this:

for (var i=arr.length; i--; )


if we just want to iterate the Array not caring it goes backwards

• Nicely found, but var can be dropped here as well I guess. Secondly, I honestly don't think you'd add functions to Array.prototype when golfing. – pimvdb Jun 7 '11 at 20:12
• var makes the counter a local and not global variable, and globals are considered bad – vsync Jun 7 '11 at 21:17
• Indeed globals are considered bad in general JavaScript programming. But in code-golfing, it saves 4 characters which is never bad :-) In code golfing, you're generally breaking a lot of readability and usability rules anyway to squeeze out the last character. – mellamokb Jun 8 '11 at 11:53
• @vsync: It seems like you're missing the point of golfing. Golf code isn't supposed to be readable, flexible, reliable or even maintainable. It's not for practical application, but just for fun challenges. Coding standards don't matter at all - all that matters is making your code short. – kba Nov 29 '11 at 6:07
• Actually, reversing for loops saves 1 character, more in a few cases. – Isiah Meadows Dec 3 '14 at 22:25

Use Mozilla's nonstandard "expression closures" feature to save many characters in a script that only needs to work in the SpiderMonkey/Firefox or Rhino engines. For example,

function foo(){return bar}


becomes

function foo()bar


See the Stack Overflow page for more such tricks.

• That's not Javascript. That's a SPACE STATION!!! – Thomas Eding Aug 20 '11 at 0:40
• ECMAScript 6 to the rescue! ->bar – Ry- Jun 10 '12 at 18:53
• ECMAScript 6: let foo = () => bar;, ironically shorter than the golfed code above. – Isiah Meadows Feb 12 '15 at 4:41
• ECMAScript 6: foo=_=>bar, even shorter. – ETHproductions Dec 22 '15 at 1:02
• that link is broken. – Cyoce Feb 11 '16 at 7:45

Repeated characters

Be creative when trying to repeat the same character:

"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
s="a";while(s.length<32)s+=s
for(s="a";s.length<32;s+=s)
for(s="aa",i=4;i--;s+=s)
s="aaaaaaaa",s+=s,s+=s
s="aaaaaaaa",s+=s+s+s
Array(33).join("a")


With ES6, this becomes even shorter:

'a'.repeat(32)


Note: It is unlikely that you use it to form a string, but the idea can be applied to form large numbers too

• new could be dropped; the Array constructor called as a function does the same as if it's called as a constructor. If the character to repeat is unimportant, it could be left out and it'll default to ",". – FireFly Aug 30 '12 at 21:59

Conditionally reverse an array with .sort

Let's say you have an array, l, and you want to reverse it if and only if someBoolean.

The naïve way to do it would be if(someBoolean)l.reverse()

Instead, you can abuse the way that JavaScript's sort function works.

if(someBoolean)l.reverse() // before
someBoolean&&l.reverse()   // golfier before
l.sort(_=>someBoolean)     // after
^^^^

• Note that the last line l.sort(_=>someConstant) is implementation dependent. It works on Firefox, but not on V8 where this fails when there's >10 elements, or there's undefined values inside the array. – Voile Dec 20 '17 at 2:46

Instead of using the lengthy parseInt to convert a number from hexadecimal:

parseInt(a,16)


Add "0x" to the beginning, then convert to a number with a usual technique:

+("0x"+a)   // 5 bytes saved


Even better solution, abusing order of operations:

"0x"+a-0    // another byte saved


Note that this last one will not work in all situations, depending on the surrounding operators.

In ES6, you can also use this trick to convert from octal or binary:

"0b"+a-0   // binary
"0o"+a-0   // octal

• An additional alternative is 0|"0x"+a – Tomas Langkaas Sep 8 '17 at 17:09

Use valueOf to make shorter function calls. Instead of:

function f(){...}
f()


use

f={valueOf:function(){...}}
+f


If you call the function f frequently enough, you will save characters because +f is 1 shorter than f().

If you usef even more than that, you can use __defineGetter__:

__defineGetter__('f',function(){...})
f


This trick also works for a function that takes 1 argument.

function f(v){...}
f(x)


Becomes

__defineSetter__('f',function(v){...})
f=x


But now it will always return v.

Edit: I forgot to mention this, but it only works for a function that doesn't take arguments.

• The var keyword is unnecessary. Same with the semicolons. n={valueOf:f} would be enough for that line. – mbomb007 May 21 '15 at 19:36
• Duly noted; edited – Cyoce May 22 '15 at 19:21
• I had no idea this was possible in JS! But there's a typo in your last example; it should be __defineGetter__('f',function(){}) rather than __defineGetter('f',function(){})__. – ETHproductions Nov 22 '16 at 15:49
• @ETHproductions I guess I missed that. Fixed. – Cyoce Nov 22 '16 at 16:05
• And it is even shorter in ES2015+: f={valueOf(){…}} or f={valueOf:_=>…}. – Toothbrush Jan 9 '19 at 12:36

Sometimes declaring a variable (or more) as function parameters can save some strokes by avoiding the var keyword. This use case is fairly rare though:

function f(){var i} => function f(i){}

Also you can use short circuit operators to avoid if statements:

if(a)b => a&&b

if(!a)b => a||b

To coerce to a number: str-0

There's a few other ideas that come to mind:

Ternary operators with functions

Ternary operators also work well as a substitute for if..then..else statements with functions...

if(a==b){
c();
}else{
if(a==d){
e();f();
}
g();
}


can be replaced with

(a==b)?c():(((a==d)&&(e()|f()))|g())

You can take this further by abusing functions that don't take parameters:

a==b?c():g(a==d&&f(e()))

If a, b, and d are numbers, you can use subtraction to test for 0.

a-b?g(a-d||f(e())):c()

Decimal Base Exponents

Another is the reduction of decimal base exponents... for example 1000000 can be replaced with 1e6

• The question asks for tips which are somewhat specific to Javascript. The ternary operator is included in the tips for all languages. – Peter Taylor Mar 17 '14 at 20:36
• Yes, but not all languages have the ternary operator, Pete... Besides, I put this in some six months ago... – WallyWest Mar 17 '14 at 22:45
• Enough languages have it: there's no point mentioning it on lots of separate per-language tips pages. It's been on the generic tips for some 11.5 months; I've commented on it today because I commented on it in a new language tips page and the person who'd posted it there mentioned that lots of other ones had it. – Peter Taylor Mar 17 '14 at 23:02
• @PeterTaylor Sure, a lot of languages have a ternary operator... But how many have ternaries for top-level expressions or functions that return void? JS is nearly on a class of its own in that respect. – Mario Carneiro Jan 30 '16 at 18:36

document.getElementById

This one's a HUGE byte-saver.

document.getElementById('a').innerHTML="foo"; //before
a.innerHTML="foo"; //after

• If you are using jQuery, it should be $(a).html('foo') – tsh Apr 8 '17 at 15:40 • How does this work? – AnnanFay Feb 9 '18 at 16:46 • – user42589 Jan 16 '19 at 22:07 • @tsh This is unrelated to jQuery. $(a) is not necessary. – user42589 Jan 16 '19 at 22:08

Use with to import methods and properties from objects into the local scope.

It becomes more apparent with longer class names or repeated use of the same one:

a=Math.max(1,2),b=Math.min(2,7),c=Math.sqrt(100)
with(Math)a=max(1,2),b=min(2,7),c=sqrt(100)

• Note: you don't need to initialize your variables while golfing. let a,b,c; would be unnecessary. – Cyoce May 18 '16 at 21:42
• @Cyoce True, thanks for the tip! – Scott May 18 '16 at 23:59

Comparing numbers by absolute value:

a*a<b*b // 7 bytes


Vastly shorter than Math.abs (8 bytes without counting ()), and like calling the function this will allow casting strings to numbers on the fly.

Sorting by arrays of multiple values, comparing them all one by one (e.g. finding minimum time durations in 01:23:45 notation):

a.map(v=>v.split:).sort(([h,m,s],[g,n,a])=>h-g||m-n||s-a)[0].join:


This example sorts 00:00:00 < 01:00:00 < 01:00:01 < 22:59:59 < 23:00:00 and finds the smallest element. This works because || short-circuits for any value that isn't falselike and so the expression h-g||m-n||s-a will evaluate the next value in the chain only when the last difference was 0.

• The standard string comparing sort will do just fine with this example – pepkin88 Sep 26 '18 at 12:39

Initialize arrays with [] instead of Array(), and add to arrays with [.length]:

a=[];       // initialize a new array
a[0]=15;    // insert element to end of array
a[1]=30;    // insert another element to end of array

• note: I know this is obvious, but if we are going to insert elements too close to index 0, it might be good idea to write it like this a=[15,30]; – ajax333221 Dec 18 '12 at 16:36
• You can also leave elements undefined (say if you want a 2 indexed version of the above -> a=[,,15,30];. Also, I think you're suggesting adding things to the array using a[a.length]=x, but a.push(x) is shorter... – Alconja Aug 7 '14 at 1:59
• Not a[a.length]. @Alconja is correct in suggesting a.push. – Isiah Meadows Feb 12 '15 at 4:42
• a.push(4) // returns index a[a.length]=5 // returns new value a=[...a,3] // returns array [...a,3] // doesn't mutate – imma Jan 26 '18 at 15:24
• well it seems breaks and pre markdown isn't working :-( – imma Jan 26 '18 at 15:26

Treat strings like you do C Strings.

Given s="hello"

s[0]


is equivalent to

s.charAt(0)


and

s.split("")[0]

• This is EcmaScript 5, but for code golf it's fine. – Konrad Borowski Jan 4 '13 at 12:03
• @xfix Yes, it's defined in EcmaScript 5, but Firefox has supported it from version 0.9. – Toothbrush Feb 24 '14 at 10:37
• Too bad JS doesn't support a[3]="d". Instead we have to use the obnoxiously long a=a.slice(0,3)+"d"+a.slice(4). – ETHproductions Dec 22 '15 at 1:08
• @ETHproductions try: a=s.split('e').join('d'); And for this case (2 L's) - s.split('ll').join('ld'); – yonatanmn Apr 23 '16 at 9:08
• what about '12345'.replace(/(..)./,'$1d') – l4m2 Apr 13 '18 at 16:19 Some extra tricks that I don't see very often, that are more JS-specific: • Use array literals and indexing as a sort of switch as an expression. You can leave out "unnecessary" elements and they'll default to undefined (which is a falsy value, by the way). E.g. [,1,,-1][i%4] would evaluate to either 1 or -1 depending on whether i is 1,5,9,13,... or 3,7,11,15,... (and we don't care about the other cases). • Similarly, use object literals when you want arbitrary strings for the keys. • This one is common to all C-style languages: (ab)use the fact that that & and | works just as well as && and || with boolean values, albeit with different precedence. Keep in mind that the single-character variants aren't short-circuiting though! • -~x is the same as x+1, and ~-x is the same as x-1. Sometimes the {bitwise,arithmetic} negation variants are useful to avoid extra parens; for instance, 4*~-n rather than 4*(n-1). • ~9 could be used as a two-character literal for the value -10 (I've never had a use for this, but it's a fun curiosity). You can use -~s instead of +s+1, and ~-s instead of +s-1, if s is a string or a number between -(2^31)-1 and 2^31. • Actually, it's also sometimes great for numbers if you want to not actually increment the number, where this has higher precedence than s+1 – Isiah Meadows Feb 11 '15 at 2:08 • And multiplication. – Isiah Meadows Feb 11 '15 at 2:08 • s-1 will also coerce s to a number. – Shaggy Sep 12 '18 at 11:57 • @Shaggy True. So will +s, s*n, -n, s/n, n-s, etc. where n is a Number (as opposed to a String). – Toothbrush Sep 12 '18 at 20:53 • Because ~ is a bitwise operator, it will treat NaN or undefined as 0, which may be useful in some cases. – user202729 Jan 9 '19 at 4:26 When it comes to comparing strings against eachother, you’d normally use x=='*'  If it is the case that x only has a few fixed options, e.g. x can only be one of the lowercase letters or the asterisk (*), then you can use JavaScript’s string comparison like this: x<'a'  In the case of limited options, this will be true if and only if x=='*' and false otherwise, saving one amazing byte! This is based on the Unicode table. For an actual example, see this revision of an answer of mine. setInterval Hacks Pass a string instead of a function to setInterval. setInterval(function(){console.log(0)},1) //before setInterval('console.log(0)',1) //after  You can also omit the last argument if you don't care about the speed at which your interval will execute. NOTE: This does not work in Firefox... setInterval('console.log(0)',1) //before setInterval('console.log(0)') //after setIntervalconsole.log(0) //after - ES6 only  • They all work in Firefox – Toothbrush Nov 5 '15 at 16:42 • @Toothbrush not the second tip. That only executes once before stopping. – Mama Fun Roll Feb 1 '16 at 17:28 • You are right, but I'm sure it worked when I tried it. – Toothbrush Feb 10 '16 at 17:24 • You can pass additional arguments to setInterval which will be passed to the function argument when it is called. For example setInterval("f(x,y)",1e3) becomes setInterval(f,1e3,x,y) for a 3 byte saving. – Shaggy Sep 12 '18 at 12:03 Determining if an array is empty The empty array is truthy in JavaScript, i.e. []?b:c returns b. This leaves us to find our own ways to determine if an array is empty. The most obvious way is .length: a.length?b:c  However, this can be shortened by 2 bytes with the in operator: 0 in a?b:c  Note: unlike in Python, x in y checks whether y has a key x; it's a shorthand for y.hasOwnProperty(x). This is, I believe, the shortest code that unconditionally detects whether a is empty. However, there are a few alternatives that work in various scenarios: a[0]?b:c  This works iff the first item in a is guaranteed to be truthy. For example, a=[1];a[0] returns 1, which is truthy; a=[];a[0] returns undefined, which is falsy; but a=[0];a[0] returns 0, which is also falsy. But in general, this trick works on arrays of chars or positive numbers. a+""?b:c  When arrays are casted to strings, the brackets are left out. [1,2,3]+"" returns the string "1,2,3". So casting a to a string will return the empty string (falsy) for the empty array, and a truthy string otherwise. Caveat: If a contains a single array which contains either nothing or a single array containing... etc., e.g. [[]], [[[[[[]]]]]], it will still be casted to the empty string. a+a?b:c  This is practically exactly the same as the above example, but a byte shorter. When + is called on two arrays, JS stupidly converts them both to strings and concatenates those. So a+a returns exactly the same thing as a+"", but doubled. • Note that 0 in a and a[0] will fail for sparse arrays such as a = [,1,2]. Thus, !a.length is the most safe way to test for an empty array. When taking advantage of type casting to string, a==0 is another solution that directly returns a boolean value. – Tomas Langkaas Sep 8 '17 at 16:06 Instead of checking if something is a string like this: var a = "aString"; if (typeof a === 'string') { runSomething(); }  You can do this: var a = "aString"; a===''+a&&runSomething();  • Nice! Can also be used for checking other types, such as numbers, n===+n, and booleans, b===!!b. – Tomas Langkaas Sep 8 '17 at 16:57 Use shorthands instead of primitives Most of these are done by any sane minifier, but not all. • 2 bytes saved true !0  • 3 bytes saved false !1  • 5 bytes saved Infinity 1/0  • 5 bytes saved undefined 0[0] (any digit works)  • Undefined is [][0] – edc65 Feb 11 '15 at 0:14 • 5 bytes saved, undefined === []._ – WallyWest Aug 17 '15 at 22:50 • 1/0 => Infinity – r3mainer Oct 13 '15 at 8:47 • undefined is also probably [].a – muhmuhten Nov 6 '15 at 5:21 • Or, if x is a variable that does not hold null or undefined, you can do x.a for undefined. – Cyoce May 24 '16 at 18:08 Another thing I came across is forcing a multidimensional array into a single-dimensional array like this: [[1,2],[3,4]].join().split(",") // ["1", "2", "3", "4"]  It does convert everything into strings, so basically only numbers/strings are possible, but it can come in handy. Calculating with strings automatically converts it into numbers anyway. EDIT: As Austin Hyde pointed out, you can flatten one level like this: [].concat.apply([],[[1,2],[3,4]])  Although it only takes it down one level, the data types remain. • yeah but if you need to use indexOf on the array later to find numbers in it...it won't find them if the array so made of strings, so this is more pure flattening – vsync Jun 7 '11 at 20:05 • [].concat.apply([],[[1,2],[3,4]]) also works, but only flattens it one level. It's two characters longer, but works on any data type. – Austin Hyde Jun 13 '11 at 18:11 • Unless you just need to pass in an array, you can flatten it like this: [].concat([1,2],[3,4]), and if you need to pass in an array and you know the contents, this works too: [].concat(a[0],a[1]). – Camilo Martin Dec 18 '12 at 12:09 • If you want to use ES6, you can use the spread operator and shorten that example to [...[1,2],...[3,4]] – Alconja Aug 7 '14 at 2:08 • You could also abuse implicit type casting to save a few bytes: ([[1,2],[3,4]]+"").split(",") – ETHproductions Nov 22 '16 at 17:05 Prefer Array#map() to Array#forEach() Self-explanatory, a flat 4 bytes saved a.forEach(function(e){/* ... */}) a.map(function(e){/* ... */})  Stack Ternary Operators Need to test many conditions, try this: a ? b : c ? d : e ? f : g  Use the comma operator Using an arrow function, and need to return something else than what your doing? Feel no need to break out the {b;return a} and instead use the comma operator:  f=>{f.map(b=>...);return a} f=>(f.map(b=>...),a)  Take advantage of = Assignment without var can be vital to shave off bytes. Since it returns the value, you can: Assign variables in function calls: Array(100).fill(100);p=100 Array(p=100).fill(p)  Stack variable assignment: a=1,b=1,c=1 a=b=c=1  Assign variables in control structures: if(b=1) {...}  Since 1 is truthy (If tested against a boolean it will convert to true), the block will run • I feel like most of these tips are already somewhere else in the thread (yes, this feels like a thread, not a question). Please remove the redundant ones. – lirtosiast Oct 16 '15 at 2:52 Use atob() and btoa() to compress/decompress strings alert('adifonoiewnfqowinfiodnasfoinqeiwnfqoiwnfoiansdfoinqowfe') //before alert(btoa('iØ¢z"{ ßª"ø¨vv¬~§©è°ú¨ ß¢&§±×èz¨Á÷')) //after  Great for some challenges. Only works on strings with a-zA-Z0-9 and no other chars. • +/ are allowed in the string as well. Also, you can sometimes use a .replace to add back in incompatible chars while still saving bytes. – ETHproductions Dec 22 '15 at 1:25 • One more thing: this doesn't work for strings of all lengths. – ETHproductions Feb 12 '16 at 17:25 • Oh, and JavaScript supports ISO-8859-1, so you can count every char in the compressed string as 1 byte. – ETHproductions Dec 13 '16 at 18:22 • Waaaait...... For real? I thought JS used UCS-2/UTF-16 for encoding. Is there an example of this working? – Mama Fun Roll Dec 13 '16 at 22:44 • Here's what I did: 1. Create a .js file that contains some chars in the range 0xA0-0xFF and save it in the ISO-8859-1 encoding. 2. Create a .html file that calls the JS file via a <script src="myfile.js"> tag. 3. Open the HTML file in any browser. I'm not sure if this proves that JS supports ISO-8859-1, but that's the best method I can think of... – ETHproductions Dec 13 '16 at 23:00 Abuse uninitialized variables, mostly for null and undefined • undefined varies, some better than others • One-time use (5 bytes saved): undefined 1..a (any digit+letter works)  • Multiple uses (8 per use - 5 bytes saved, 10 bytes for 2 uses) undefined;undefined var u;u;u  • Existing declaration (8 per use - 5 bytes saved, 5 bytes for 1 use, 13 bytes for 2 uses) var x;undefined var x,u;u var x;undefined;undefined var x,u;u;u  • null varies, generally better replaced in larger golfs • If there is a declaration anywhere, replace it unless null is specifically required (3 per use - 2 bytes saved). var x;null var x,n;n  • Single uses: • If no variable declaration exists, do not change. • If any undefined exists (in any form), declare an unused variable (5 bytes saved if one of each). v==null;undefined var u;v==u;u  • If more than two such tests exist, declare an unused variable (two are equal). a==null;b==null;c==null var u;a==u;b==u;c==u  • Otherwise, keep as null • Multiple uses: • Declare an unused variable, unless null is specifically required (2 is equivalent). null;null;null var u;u;u;u  • Prefer to avoid these tests when possible. Aim for implicit boolean tests (if(0);) • Another way to get undefined easily is 1..a – Dom Hastings May 19 '16 at 12:05 • Good catch - I fixed it – Isiah Meadows May 19 '16 at 23:37 • If you're restricted to non-alphanumeric characters, [].$ will also equal undefined – WallyWest Sep 12 '18 at 23:11
• undefined without digits: [][[]] – Kamil Kiełczewski Jun 26 at 10:13

Less/Greater than "10/100/1000..." vs "9/99/999...":

//for(i=0;i<20;i++){
if(i<10){}else{}
if(i>9){}else{}
//}


Note: Just remember to swap what is inside the if with the else

For strings and arrays, instead of using a=b.length>a.length?b:a to set a to b if b.length > a.length, you can use a=b[a.length]?b:a.

Note: If b is an array and contains either 0 or false, you'll have to use a=b[a.length]!=null?b:a (still one character shorter).

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)){/* ... */}

• Don't get what's going on here but from your description +!!x is shorter and more concise. – George Reith Nov 5 '15 at 17:27