174
\$\begingroup\$

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

\$\endgroup\$
4
  • \$\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
  • 1
    \$\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

98 Answers 98

9
\$\begingroup\$

Converting a number from hexadecimal

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
\$\endgroup\$
1
  • 2
    \$\begingroup\$ An additional alternative is 0|"0x"+a \$\endgroup\$ Sep 8, 2017 at 17:09
9
\$\begingroup\$

tl;dr: Use ES6 features!

Arrow functions

Doc: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/arrow_functions
Example:

s = x => x*x
// s = function (x) {
//   return x * x;
// }
\$\endgroup\$
7
  • \$\begingroup\$ Arrow functions were already mentioned on Oct 13 '13 at 15:42. But that for..of is cool. Even shorter than for each..in. \$\endgroup\$
    – manatwork
    Jan 7, 2014 at 15:11
  • 2
    \$\begingroup\$ The array comprehension syntax seems to be wrong. According to the documentation should be like in Python: b = [s(x) for (x of a)]. \$\endgroup\$
    – manatwork
    Jan 7, 2014 at 15:15
  • \$\begingroup\$ @manatwork The above samples run fine in Traceur's REPL \$\endgroup\$
    – Florent
    Jan 7, 2014 at 15:31
  • \$\begingroup\$ No idea about Traceur, but you mentioned ECMAScript and pointed to Mozilla documentation. And array comprehensions in none of them looks like you wrote it. \$\endgroup\$
    – manatwork
    Jan 7, 2014 at 15:39
  • 1
    \$\begingroup\$ Array comprehensions were actually pulled midway through. \$\endgroup\$
    – Claudia
    Dec 3, 2014 at 22:20
9
\$\begingroup\$

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)

\$\endgroup\$
2
  • 2
    \$\begingroup\$ and 2**nin ES6 \$\endgroup\$
    – Cétia
    Jun 27, 2018 at 7:57
  • 1
    \$\begingroup\$ @Cétia That’s ES7. \$\endgroup\$ Jan 16, 2019 at 22:13
8
\$\begingroup\$

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:

So instead of this iteration:

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

\$\endgroup\$
7
  • 2
    \$\begingroup\$ 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. \$\endgroup\$
    – pimvdb
    Jun 7, 2011 at 20:12
  • \$\begingroup\$ var makes the counter a local and not global variable, and globals are considered bad \$\endgroup\$
    – vsync
    Jun 7, 2011 at 21:17
  • 12
    \$\begingroup\$ 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. \$\endgroup\$
    – mellamokb
    Jun 8, 2011 at 11:53
  • 13
    \$\begingroup\$ @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. \$\endgroup\$
    – kba
    Nov 29, 2011 at 6:07
  • 1
    \$\begingroup\$ Actually, reversing for loops saves 1 character, more in a few cases. \$\endgroup\$
    – Claudia
    Dec 3, 2014 at 22:25
8
\$\begingroup\$

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.

\$\endgroup\$
6
  • 2
    \$\begingroup\$ That's not Javascript. That's a SPACE STATION!!! \$\endgroup\$ Aug 20, 2011 at 0:40
  • 1
    \$\begingroup\$ ECMAScript 6 to the rescue! ->bar \$\endgroup\$
    – Ry-
    Jun 10, 2012 at 18:53
  • 5
    \$\begingroup\$ ECMAScript 6: let foo = () => bar;, ironically shorter than the golfed code above. \$\endgroup\$
    – Claudia
    Feb 12, 2015 at 4:41
  • 3
    \$\begingroup\$ ECMAScript 6: foo=_=>bar, even shorter. \$\endgroup\$ Dec 22, 2015 at 1:02
  • \$\begingroup\$ that link is broken. \$\endgroup\$
    – Cyoce
    Feb 11, 2016 at 7:45
8
\$\begingroup\$

Use if(~a.indexOf(b)) instead of if(a.indexOf(b)!=-1)

\$\endgroup\$
1
8
\$\begingroup\$

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
                      ^^^^
\$\endgroup\$
1
  • \$\begingroup\$ 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. \$\endgroup\$
    – Voile
    Dec 20, 2017 at 2:46
8
\$\begingroup\$

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.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ Sep 8, 2017 at 16:06
  • 2
    \$\begingroup\$ @TomasLangkaas but [0]==0 as well, so a==0 doesn't always work \$\endgroup\$
    – pxeger
    Dec 19, 2021 at 21:27
8
\$\begingroup\$

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.

\$\endgroup\$
1
  • 3
    \$\begingroup\$ The standard string comparing sort will do just fine with this example \$\endgroup\$
    – pepkin88
    Sep 26, 2018 at 12:39
7
\$\begingroup\$

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

\$\endgroup\$
7
\$\begingroup\$

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

\$\endgroup\$
1
  • 8
    \$\begingroup\$ 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 ",". \$\endgroup\$
    – FireFly
    Aug 30, 2012 at 21:59
7
\$\begingroup\$

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)
    
\$\endgroup\$
8
  • 1
    \$\begingroup\$ Undefined is [][0] \$\endgroup\$
    – edc65
    Feb 11, 2015 at 0:14
  • 2
    \$\begingroup\$ 5 bytes saved, undefined === []._ \$\endgroup\$ Aug 17, 2015 at 22:50
  • 10
    \$\begingroup\$ 1/0 => Infinity \$\endgroup\$
    – r3mainer
    Oct 13, 2015 at 8:47
  • 4
    \$\begingroup\$ undefined is also probably [].a \$\endgroup\$
    – muhmuhten
    Nov 6, 2015 at 5:21
  • 2
    \$\begingroup\$ Or, if x is a variable that does not hold null or undefined, you can do x.a for undefined. \$\endgroup\$
    – Cyoce
    May 24, 2016 at 18:08
6
\$\begingroup\$

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
\$\endgroup\$
5
  • 8
    \$\begingroup\$ 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]; \$\endgroup\$
    – ajax333221
    Dec 18, 2012 at 16:36
  • 7
    \$\begingroup\$ 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... \$\endgroup\$
    – Alconja
    Aug 7, 2014 at 1:59
  • \$\begingroup\$ Not a[a.length]. @Alconja is correct in suggesting a.push. \$\endgroup\$
    – Claudia
    Feb 12, 2015 at 4:42
  • \$\begingroup\$ a.push(4) // returns index a[a.length]=5 // returns new value a=[...a,3] // returns array [...a,3] // doesn't mutate \$\endgroup\$
    – imma
    Jan 26, 2018 at 15:24
  • \$\begingroup\$ well it seems breaks and pre markdown isn't working :-( \$\endgroup\$
    – imma
    Jan 26, 2018 at 15:26
6
\$\begingroup\$

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

\$\endgroup\$
6
\$\begingroup\$

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

\$\endgroup\$
4
  • \$\begingroup\$ The question asks for tips which are somewhat specific to Javascript. The ternary operator is included in the tips for all languages. \$\endgroup\$ Mar 17, 2014 at 20:36
  • 1
    \$\begingroup\$ Yes, but not all languages have the ternary operator, Pete... Besides, I put this in some six months ago... \$\endgroup\$ Mar 17, 2014 at 22:45
  • \$\begingroup\$ 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. \$\endgroup\$ Mar 17, 2014 at 23:02
  • \$\begingroup\$ @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. \$\endgroup\$ Jan 30, 2016 at 18:36
6
\$\begingroup\$

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.

\$\endgroup\$
6
  • \$\begingroup\$ 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 \$\endgroup\$
    – Claudia
    Feb 11, 2015 at 2:08
  • \$\begingroup\$ And multiplication. \$\endgroup\$
    – Claudia
    Feb 11, 2015 at 2:08
  • \$\begingroup\$ s-1 will also coerce s to a number. \$\endgroup\$
    – Shaggy
    Sep 12, 2018 at 11:57
  • \$\begingroup\$ @Shaggy True. So will +s, s*n, -n, s/n, n-s, etc. where n is a Number (as opposed to a String). \$\endgroup\$
    – Toothbrush
    Sep 12, 2018 at 20:53
  • \$\begingroup\$ Because ~ is a bitwise operator, it will treat NaN or undefined as 0, which may be useful in some cases. \$\endgroup\$
    – DELETE_ME
    Jan 9, 2019 at 4:26
6
\$\begingroup\$

document.getElementById

This one's a HUGE byte-saver.

document.getElementById('a').innerHTML="foo"; //before
a.innerHTML="foo"; //after
\$\endgroup\$
4
  • \$\begingroup\$ If you are using jQuery, it should be $(a).html('foo') \$\endgroup\$
    – tsh
    Apr 8, 2017 at 15:40
  • 1
    \$\begingroup\$ How does this work? \$\endgroup\$
    – AnnanFay
    Feb 9, 2018 at 16:46
  • 1
    \$\begingroup\$ @Annan See Do DOM tree elements with ids become global variables?. \$\endgroup\$ Jan 16, 2019 at 22:07
  • 5
    \$\begingroup\$ @tsh This is unrelated to jQuery. $(a) is not necessary. \$\endgroup\$ Jan 16, 2019 at 22:08
6
\$\begingroup\$

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)
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Note: you don't need to initialize your variables while golfing. let a,b,c; would be unnecessary. \$\endgroup\$
    – Cyoce
    May 18, 2016 at 21:42
  • \$\begingroup\$ @Cyoce True, thanks for the tip! \$\endgroup\$
    – Scott
    May 18, 2016 at 23:59
6
\$\begingroup\$

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.

\$\endgroup\$
5
  • \$\begingroup\$ The var keyword is unnecessary. Same with the semicolons. n={valueOf:f} would be enough for that line. \$\endgroup\$
    – mbomb007
    May 21, 2015 at 19:36
  • \$\begingroup\$ Duly noted; edited \$\endgroup\$
    – Cyoce
    May 22, 2015 at 19:21
  • \$\begingroup\$ 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(){})__. \$\endgroup\$ Nov 22, 2016 at 15:49
  • \$\begingroup\$ @ETHproductions I guess I missed that. Fixed. \$\endgroup\$
    – Cyoce
    Nov 22, 2016 at 16:05
  • \$\begingroup\$ And it is even shorter in ES2015+: f={valueOf(){…}} or f={valueOf:_=>…}. \$\endgroup\$
    – Toothbrush
    Jan 9, 2019 at 12:36
5
\$\begingroup\$

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.

\$\endgroup\$
11
  • 1
    \$\begingroup\$ 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 \$\endgroup\$
    – vsync
    Jun 7, 2011 at 20:05
  • 2
    \$\begingroup\$ [].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. \$\endgroup\$ Jun 13, 2011 at 18:11
  • 1
    \$\begingroup\$ 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]). \$\endgroup\$ Dec 18, 2012 at 12:09
  • 3
    \$\begingroup\$ If you want to use ES6, you can use the spread operator and shorten that example to [...[1,2],...[3,4]] \$\endgroup\$
    – Alconja
    Aug 7, 2014 at 2:08
  • 1
    \$\begingroup\$ You could also abuse implicit type casting to save a few bytes: ([[1,2],[3,4]]+"").split(",") \$\endgroup\$ Nov 22, 2016 at 17:05
5
\$\begingroup\$

Treat strings like you do C Strings.

Given s="hello"

s[0]

is equivalent to

s.charAt(0)

and

s.split("")[0]
\$\endgroup\$
7
  • 1
    \$\begingroup\$ This is EcmaScript 5, but for code golf it's fine. \$\endgroup\$
    – 0..
    Jan 4, 2013 at 12:03
  • 1
    \$\begingroup\$ @xfix Yes, it's defined in EcmaScript 5, but Firefox has supported it from version 0.9. \$\endgroup\$
    – Toothbrush
    Feb 24, 2014 at 10:37
  • 2
    \$\begingroup\$ 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). \$\endgroup\$ Dec 22, 2015 at 1:08
  • \$\begingroup\$ @ETHproductions try: a=s.split('e').join('d'); And for this case (2 L's) - s.split('ll').join('ld'); \$\endgroup\$
    – yonatanmn
    Apr 23, 2016 at 9:08
  • 1
    \$\begingroup\$ what about '12345'.replace(/(..)./,'$1d') \$\endgroup\$
    – l4m2
    Apr 13, 2018 at 16:19
5
\$\begingroup\$

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.

\$\endgroup\$
5
\$\begingroup\$

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
setInterval`console.log(0)` //after - ES6 only
\$\endgroup\$
4
  • \$\begingroup\$ They all work in Firefox \$\endgroup\$
    – Toothbrush
    Nov 5, 2015 at 16:42
  • \$\begingroup\$ @Toothbrush not the second tip. That only executes once before stopping. \$\endgroup\$ Feb 1, 2016 at 17:28
  • \$\begingroup\$ You are right, but I'm sure it worked when I tried it. \$\endgroup\$
    – Toothbrush
    Feb 10, 2016 at 17:24
  • 1
    \$\begingroup\$ 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. \$\endgroup\$
    – Shaggy
    Sep 12, 2018 at 12:03
5
\$\begingroup\$

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

\$\endgroup\$
1
  • 1
    \$\begingroup\$ 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. \$\endgroup\$
    – lirtosiast
    Oct 16, 2015 at 2:52
5
\$\begingroup\$

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.

\$\endgroup\$
6
  • \$\begingroup\$ +/ are allowed in the string as well. Also, you can sometimes use a .replace to add back in incompatible chars while still saving bytes. \$\endgroup\$ Dec 22, 2015 at 1:25
  • \$\begingroup\$ One more thing: this doesn't work for strings of all lengths. \$\endgroup\$ Feb 12, 2016 at 17:25
  • 2
    \$\begingroup\$ Oh, and JavaScript supports ISO-8859-1, so you can count every char in the compressed string as 1 byte. \$\endgroup\$ Dec 13, 2016 at 18:22
  • \$\begingroup\$ Waaaait...... For real? I thought JS used UCS-2/UTF-16 for encoding. Is there an example of this working? \$\endgroup\$ Dec 13, 2016 at 22:44
  • \$\begingroup\$ 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... \$\endgroup\$ Dec 13, 2016 at 23:00
5
\$\begingroup\$

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

\$\endgroup\$
4
  • \$\begingroup\$ Another way to get undefined easily is 1..a \$\endgroup\$ May 19, 2016 at 12:05
  • \$\begingroup\$ Good catch - I fixed it \$\endgroup\$
    – Claudia
    May 19, 2016 at 23:37
  • \$\begingroup\$ If you're restricted to non-alphanumeric characters, [].$ will also equal undefined \$\endgroup\$ Sep 12, 2018 at 23:11
  • \$\begingroup\$ undefined without digits: [][[]] \$\endgroup\$ Jun 26, 2020 at 10:13
4
\$\begingroup\$

Prefer Array#map() to Array#forEach()

Self-explanatory, a flat 4 bytes saved

a.forEach(function(e){/* ... */})
a.map(function(e){/* ... */})
\$\endgroup\$
4
\$\begingroup\$

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();
\$\endgroup\$
1
  • \$\begingroup\$ Nice! Can also be used for checking other types, such as numbers, n===+n, and booleans, b===!!b. \$\endgroup\$ Sep 8, 2017 at 16:57
4
\$\begingroup\$

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
\$\endgroup\$
2
  • 4
    \$\begingroup\$ And, if you don't mind changing the original array, [a.pop()], at 9 characters. \$\endgroup\$ Sep 8, 2017 at 16:53
  • 1
    \$\begingroup\$ [a.at(-1)] is 10 bytes without modify the array. It requires a more recently released interpreter though. \$\endgroup\$
    – tsh
    Feb 23, 2023 at 5:59
4
\$\begingroup\$

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

if(v=='hello'){
  j=1
}else if(v=='goodbye'){
  j=2
//...

consider:

j={hello:1,goodbye:2,...}[v]
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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