Undefined Behavior in JS

JavaScript has a tendency to do strange things, particularly when faced with operations on dissimilar types. This document is not meant to be a comprehensive list of undefined behavior, but rather a demonstration of the possibilities. These are not necessarily wrong (in fact, these results can be explained by the specifications), but are nevertheless odd.

Note: throughout this text, input to the JavaScript interpreter is shown with a > prompt, and the result is shown below; identical to the format of the JavaScript console in many browsers. Comments are inserted into the code blocks with JavaScript comment syntax //. Additionally, these expressions have been evaluated in a variety of browsers, but this behavior may vary by browser and/or platform.

The + can concatenate or add, but sometimes strange behavior occurs.

> {} + {}
NaN 
> {} + []
0
> [] + {}
"[object Object]"
> [] + []
""
> [] + 1
"1"
> null + undefined
NaN

Some typeof behavior. The built-in function typeof returns a string representing the type of its argument.

> typeof(null)
"object"
> typeof(NaN)
"number"

Sometimes, an expression seems to be one type, and putting it in typeof gets us something else entirely:

> {} + []
0 // the number zero, _not_ a string
> typeof({} + [])
"string" // huh?

Also, if null is an object, as stated by typeof, then the following makes no sense:

> 2*{}
NaN // okay, this makes sense
> 2*null
0 // this doesn't
> null + 2
2
> (null+1)/null
Infinity

typeof said that null was an object. Now null is behaving like the number 0!

More mathematical expressions. In many cases, an empty array [] behaves like zero, and sometimes an object behaves like zero. Additionally, subtracting strings works just fine, and negative zero exists:

> [] - []
0
> [] - {}
NaN
> {} - []
0
> {} - {}
NaN
> []/2
0
> 1/[]
Infinity
> []-1
-1
> {}-1
-1
> "1" - "1"
0
> -0
-0
> -[].length
-0
> -0 * 0
-0
> null*null
0
> []%true
0

Wrapping an expression involving an object in parentheses can change the value:

> {}+1
1
> ({}+1)
"[object Object]1"
> {}-1
-1
> ({}-1)
NaN

Equality is also fun, the == and != operators perform type coercion:

> 0 == ''
true
> false == '0'
true
> ' \t\r\n ' == 0
true
> undefined == null
true

Comparisons may disagree with equality:

> null > 0
false
> null < 0
false
> null >= 0
true
> null <= 0
true
> null == 0
false
> null === 0
false

Similarly, with undefined:

> null > undefined
false
> null < undefined
false
> null >= undefined
false
> null <= undefined
false
> null == undefined
true
> null === undefined
false

Practical Applications

A simple usage example. The golden ratio:

> ((0 == '') + Math.sqrt((-([]-true) + [] + null*null)/-(-true-true)))*([]+((' ' == 0) - '0'))/(-([]-true-[]-true))

1.618033988749895

Granted, it's a mess, but we can do better. An approximation of pi, without any alphanumerics:

> ((-!''-!!'|'-!'')+[]+(([]+((''=='')*!({}-{}))+([]-[]))/((!!'"')+!''))*((!'' + !!'')+[]+(!'' + !'.')))/((-!''+!'\\')+[]+(!''+[]/([]+(!!"'"+([]-[]))))+((!'' + ([]-[]))+(!!{}*!![])+(!''*!('"'=="'"))))

3.1415929203539825

This is done by creating the approximation of pi, 355/113, with a whole lot of operator abuse.

With a function and some loops, we can approximate Euler's number e:

> function π(_){___=(!'');for(__=-(~'.'+~'.');__<=_;__++)___*=__;return ___};____=-(!(~~{})+~!'');for(ß=-~[];ß<((!!"~"+!!'/')+[]+(!''+!"'"))*-(~[]+~{});++ß)____+=(!''*!"")/π(ß);____;

2.7182818284590455

Valid variable names in JavaScript obey a strange set of laws. In particular, a large number of Unicode characters can be used without any trouble. This handy tool is great for checking if a given character sequence is valid.

Using a loop to approximate the reciprocal Fibonacci constant:

> µ=[],µ[-(-[])]=-(-[]-!''),µ[[]-!!'~']=''*'',Ω=''/!!'\\';for(π=!!"'"*!!'"';π<((!(''/'')+~~(""/""))<<(!([]/[])+!(-~{}/[]))<<(-(~[]|{}))<<(-~{}))+[]+""*"";µ[π]=µ[π+[]-!'']+µ[π+~'~'-(-~'~')],Ω+=((''^!'')/µ[π+~[]&~[]]),++π)Ω;

3.359885666243178