155
\$\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\$
3
  • \$\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 '11 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 '11 at 13:44
  • \$\begingroup\$ This link has a bunch of tips relevant here. \$\endgroup\$ Feb 12 '15 at 4:53

89 Answers 89

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 '11 at 20:12
  • \$\begingroup\$ var makes the counter a local and not global variable, and globals are considered bad \$\endgroup\$
    – vsync
    Jun 7 '11 at 21:17
  • 11
    \$\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 '11 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 '11 at 6:07
  • 1
    \$\begingroup\$ Actually, reversing for loops saves 1 character, more in a few cases. \$\endgroup\$ Dec 3 '14 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 '11 at 0:40
  • 1
    \$\begingroup\$ ECMAScript 6 to the rescue! ->bar \$\endgroup\$
    – Ry-
    Jun 10 '12 at 18:53
  • 5
    \$\begingroup\$ ECMAScript 6: let foo = () => bar;, ironically shorter than the golfed code above. \$\endgroup\$ Feb 12 '15 at 4:41
  • 3
    \$\begingroup\$ ECMAScript 6: foo=_=>bar, even shorter. \$\endgroup\$ Dec 22 '15 at 1:02
  • \$\begingroup\$ that link is broken. \$\endgroup\$
    – Cyoce
    Feb 11 '16 at 7:45
8
\$\begingroup\$

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

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

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)

\$\endgroup\$
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 '17 at 2:46
8
\$\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 '17 at 17:09
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 '12 at 21:59
7
\$\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 '15 at 19:36
  • \$\begingroup\$ Duly noted; edited \$\endgroup\$
    – Cyoce
    May 22 '15 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 '16 at 15:49
  • \$\begingroup\$ @ETHproductions I guess I missed that. Fixed. \$\endgroup\$
    – Cyoce
    Nov 22 '16 at 16:05
  • \$\begingroup\$ And it is even shorter in ES2015+: f={valueOf(){…}} or f={valueOf:_=>…}. \$\endgroup\$
    – Toothbrush
    Jan 9 '19 at 12:36
7
\$\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
  • 2
    \$\begingroup\$ The standard string comparing sort will do just fine with this example \$\endgroup\$
    – pepkin88
    Sep 26 '18 at 12:39
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
  • \$\begingroup\$ Undefined is [][0] \$\endgroup\$
    – edc65
    Feb 11 '15 at 0:14
  • 2
    \$\begingroup\$ 5 bytes saved, undefined === []._ \$\endgroup\$ Aug 17 '15 at 22:50
  • 10
    \$\begingroup\$ 1/0 => Infinity \$\endgroup\$
    – r3mainer
    Oct 13 '15 at 8:47
  • 4
    \$\begingroup\$ undefined is also probably [].a \$\endgroup\$
    – muhmuhten
    Nov 6 '15 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 '16 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 '12 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 '14 at 1:59
  • \$\begingroup\$ Not a[a.length]. @Alconja is correct in suggesting a.push. \$\endgroup\$ Feb 12 '15 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 '18 at 15:24
  • \$\begingroup\$ well it seems breaks and pre markdown isn't working :-( \$\endgroup\$
    – imma
    Jan 26 '18 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 '14 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 '14 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 '14 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 '16 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\$ Feb 11 '15 at 2:08
  • \$\begingroup\$ And multiplication. \$\endgroup\$ Feb 11 '15 at 2:08
  • \$\begingroup\$ s-1 will also coerce s to a number. \$\endgroup\$
    – Shaggy
    Sep 12 '18 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 '18 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 '19 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
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 '16 at 21:42
  • \$\begingroup\$ @Cyoce True, thanks for the tip! \$\endgroup\$
    – Scott
    May 18 '16 at 23:59
6
\$\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\$
1
  • 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 '17 at 16:06
6
+50
\$\begingroup\$

Converting an array of strings into numbers

Take the array ["32", "0x30", "0o10", "7.642", "1e3"]. The simple way to convert this to numbers would be .map(n=>+n) or .map(Number).

However, assuming you know everything is a valid number, you can simply use .map(eval), saving at least a byte.

\$\endgroup\$
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 '11 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 '11 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 '12 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 '14 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 '16 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\$ Jan 4 '13 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 '14 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 '15 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 '16 at 9:08
  • 1
    \$\begingroup\$ what about '12345'.replace(/(..)./,'$1d') \$\endgroup\$
    – l4m2
    Apr 13 '18 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 '15 at 16:42
  • \$\begingroup\$ @Toothbrush not the second tip. That only executes once before stopping. \$\endgroup\$ Feb 1 '16 at 17:28
  • \$\begingroup\$ You are right, but I'm sure it worked when I tried it. \$\endgroup\$
    – Toothbrush
    Feb 10 '16 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 '18 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 '15 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 '15 at 1:25
  • \$\begingroup\$ One more thing: this doesn't work for strings of all lengths. \$\endgroup\$ Feb 12 '16 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 '16 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 '16 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 '16 at 23:00
5
\$\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 '17 at 16:57
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\$

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 '16 at 12:05
  • \$\begingroup\$ Good catch - I fixed it \$\endgroup\$ May 19 '16 at 23:37
  • \$\begingroup\$ If you're restricted to non-alphanumeric characters, [].$ will also equal undefined \$\endgroup\$ Sep 12 '18 at 23:11
  • \$\begingroup\$ undefined without digits: [][[]] \$\endgroup\$ Jun 26 '20 at 10:13
3
\$\begingroup\$

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

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

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

\$\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.