
WTFJS? - mcantelon
http://wtfjs.com/
======
mrcharles
NaN === NaN being false is extremely handy. If you are trying to track down a
rogue NaN in some code, equating a variable against itself finds it
immediately. This is also the same in most other languages (I use it all the
time in C++).

~~~
rflrob
Is there an advantage to doing that as opposed to using isNaN()?

~~~
mnemonicsloth
IIRC, it's a speed hack in the IEEE floating point standard.

NaN can happen for a lot of different reasons. You might have divided by zero
because your code is broken, or you might have divided by epsilon because your
algorithm isn't stable on this problem. [1]

This test checks to make sure none of {f, g, x, y, intermediate_values} were
ever NaN, wihtout having to test each one every step of the way.

    
    
        if (  f(x) == g(y)  )
    

Which is a big deal if it's the guard on an inner loop in some numerical code.

[1] I'm fuzzy on the details. Corrections solicited.

~~~
endtime
If it's just a debugging trick, though, then speed hacks seem less useful.

------
meastham
NaN === NaN is guaranteed to be false by IEEE 754. Hardly a wtf.

Actually most of these posts seem to be the author misunderstanding floating
point numbers. Perhaps he should learn what he's doing before he blames the
language.

~~~
kevingadd
This suggests that you don't actually know what the === operator is. To
summarize:

== - 'values are equal' - in this case, are these two numbers equal? The IEEE
spec would say no. I agree!

=== - 'both sides are exactly the same' - or, in more technical terms, are
both the values and types of each argument exactly identical. In this case,
the answer is yes, absolutely. === is not a numerical comparison and should
not be.

~~~
meastham
=== means value and type are equal. In this case, the types are equal, but the
values are not. I'd argue that NaN === NaN being true would imply a broken
implementation of IEEE 754, and the designers of JS seem to agree with me.

~~~
kevingadd
What benefit is created by having a hierarchy of comparison operators in which
there is no actual way to compare two numbers for semantic (not numeric)
equivalence?

If (NaN == NaN) == false, and (NaN === NaN) == false, how would you implement
an isNaN() function? If your answer is 'depend on the VM', I find that a bit
strange.

~~~
pmjordan
typeof(NaN) should still be 'number', which would identify it uniquely. The
irony of the value "Not a Number" having type "Number" is not lost on me,
however.

------
olliej
A reasonable number of these "wtf"s are just more examples of people failing
to understand floating point. _sigh_

~~~
kevingadd
The question is who failed to understand floating point: The authors of the JS
specification, the authors of the JS runtime, or the people writing the
javascript that demonstrates the 'wtf'? Is the answer "all three"?

~~~
jluxenberg
The real WTF is, why does a person writing some Javascript code need to
understand floating point? What high-performance calculations are you doing in
you Javascript wouldn't be easier, more accurate, and not that much slower
using fixed point math?

~~~
mbrubeck
With fixed point or arbitrary-precision math, you either need to (a) set the
level of precision explicitly, which is just as bad about forcing the user to
understand the underlying model, or (b) have the language choose the level of
precision heuristically, and have even more unpredictable performance and
rounding characteristics.

There's no language that lets you do real-world work with numbers like sqrt(2)
or PI without understanding precision and representation to some degree.

~~~
tumult
JavaScript's brilliant solution is to just not have integers. At all. That's
better, somehow?

~~~
mbrubeck
No, I think JavaScript's "floats everywhere" is worse than most languages. I
prefer languages like Python/Ruby that have one arbitrary-precision integer
type and one floating point type, or languages like Haskell or Lisp that have
a rich selection of floating/fixed/abitrary/rational types with well-defined
performance. But some (not all) of the WTFs here exist in all of those
languages too. Eventually, programmers working with numbers really do need to
learn how to use different numerical representations.

~~~
godDLL
Could you please grace us with a code sample for all of these? I'm not
intimately familiar with Haskell, Lisp or Ruby.

    
    
      >>> from decimal import *
      >>> Decimal('0.3') == Decimal('0.1') + Decimal('0.2')
      True
      >>> Decimal('NaN') == Decimal('NaN')
      False
      >>>

~~~
eslifka
You only get that result in python by importing the decimal library. The
standard behavior in python is (.1 + .2 == .3) == False

However, your code example makes the excellent point that python has such a
library available, whereas Javascript does not. At least, not as easily as an
import.

------
andreyf
Psht, floating point WTF's are for noobs. == is where the money is at.
Straight from my V8 console:

    
    
        >>> x = new Boolean;
        false
        >>> b = (x || !x);
        false
        >>> Boolean(b == false) && Boolean(x == false) && Boolean(b) && Boolean(x)
        true

------
brianleroux
Eh, msg me on twitter (same username) if you have better wtfs or want to
contribute. The idea isn't to prove how awesome knowledgeable you are but
rather to have a good laugh and MAYBE point out some of the less intuitive
aspects of the language we all love to hate on.

~~~
icefox
Just pick up JavsaScript: The Good Parts by Douglas Crockford. He has a
chapter called "The bad parts".

------
Tichy
"(x=[].reverse)() === window // true"

Didn't understand this one at first, but I guess it is easy: first x becomes
the reverse function of arrays, then it is called with this === window. So it
amounts to window.reverse(). Just looked it up, and reverse() works in place,
so window.reverse() === window - although it is potentially different from
before.

~~~
andreyf
No, it amonts to Array.prototype.reverse.call(window) - window doesn't have a
reverse method AFAIK, so window.reverse() will raise a TypeError (since you
can't call something "undefined").

~~~
Tichy
are you sure? i thought in js functions are not really tied to "their" object,
instead they receive an implicit this argument. wouldn't x belong to window
here? that is, window doesn't have reverse, but now it has x

------
waldrews
In what language is 0.1 + 0.2 == 0.3? (I guess C# with decimal literals, but
you'd have to specify that with a suffix)

~~~
Locke1689

      Prelude> (0.1 + 0.2) == 0.3
      False
      Prelude Ratio> 1 % 10 + 2 % 10 == 3 % 10
      True

~~~
jrockway
Or:

    
    
        ghci> 0.1 + 0.2 == (0.3 :: Ratio Int)
        True
    

Same type, less syntax.

------
pixelcort
`typeof null` is 'object', not Object. (It's a string that contains the word
object.)

~~~
invisible
If the programming can't handle a null object, check that the object is of the
required type (by setting a key) or check that the object is not null. It's
dumb to expect null to not be an object when EVERYTHING is an object in JS
(except undefined, which is special). Furthermore, the programmer would be
setting a value to null if they are checking for null (are there any other
instances where null occurs without explicitly setting?).

------
statictype
>(function(){ if(false) var window; return window }()) === window

>JavaScript interpreter checks all variable declarations in scope before
execution.

This is another way of saying that all variable declarations are scoped at the
function level, not the individual block level. This is why generating
closures in a loop is broken in javascript (Although in just about every other
language as well, closures in a loop give surprising results at first -
including, I think, arc?)

To get a new scope, you have to use the anonymous function trick:

    
    
        (function(){
           var x;//new scope
           ...
          })()

~~~
andreyf
This is not a WTF if you just know where a language draws scope boundaries -
for most languages, it isn't just along the {}'s.

~~~
statictype
It's a WTF in the sense that every other language with curly braces scope at
the block level.

------
techiferous
This is awesome.

<shameless plug>

I feel compelled to mention my WTF JavaScript library, even though it is
something completely different: [http://github.com/techiferous/wtf-
js/blob/master/javascripts...](http://github.com/techiferous/wtf-
js/blob/master/javascripts/wtf.js)

It's a library for dealing with World Time Format conversions:
<http://worldtimeformat.com/>

</shameless plug>

------
kwamenum86
When you run reverse with a context of anything besides an array you end up
getting back that context. This is why assigning [].reverse to x, then running
x() returns window. It is an interesting quirk. Not sure if this is the js
specified behavior though.

~~~
andreyf
Yes, this is JS specified behavior. If there is no activation object (one
referenced by an identifier before the `.'), the value of `this' is set to the
global object.

------
tedunangst
Floating point is hard, let's go shopping.

------
tszming
FYI,

Some guy registered WTFPHP.com on 2010/02/12

------
invisible
A bit of Computer Science knowledge would go a long way in explaining these:
e.g. "Foo" + + "Bar" === "FooNaN" (attempting to do unary + on "Bar"). Tons of
other examples as documented here, but some of these are a "bit" strange yes
;).

------
jrockway
I am no fan of Javascript, but most of these WTFs make sense to me. The
111111111100 one is unexpected, although there is probably a good explanation.
(Like "alert takes a string, you passed a number. nasal demons.")

~~~
mrcharles
Wouldn't that have more to do with the fact that javascript uses floats for
everything? It's probably exceeding precision at a guess.

~~~
malkia
Is it? I thought Javascript has integer type.

Say for example Lua (by default) is configured to use only double. It can be
configured to use single-float, or even integer - but only one numeric type.

~~~
pmjordan
Standard JavaScript uses doubles everywhere. They get casted to 32-bit signed
integers for bitwise operations, the results are casted back. It's a little
odd, but consistent at least.

~~~
andreyf
A little odd and a lot slow, if you do them a lot (js-protobuf, I'm looking at
you).

~~~
jrockway
Execution tracing should eliminate the cast if it is not necessary.

------
nandemo
WTFHN? Why is this voted up? Just because you don't immediately understand
something doesn't make it a WTF.

------
jetako
isNaN(null) == false; is the only wtf I can never remember to avoid, because I
can't rationalize it no matter how hard I try.

Edit: I get it now. null coverts to 0

~~~
alunny
it's because of type conversion - null has the same value as 0 (as in `(+
null)`), so it is a number

~~~
jetako
Yea, what a weird mental block, not realizing null is equivalent to 0, even in
math statements. I guess it's because null is not the same as 0 when converted
to a String.

------
tmountain
Eh, no biggie, a few pages of gotchas. If we were talking about PHP, I could
write a few volumes.

