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++).
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.
It depends on the implementation. In C, it is quite easy to have n != n optimized away when compilers have their compiler flags set on. That's why you should use isnan to test nan instead of any other techniques when using C or C++.
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.
Yup; Number.MIN_VALUE has the minimum possible mantissa and exponent, for example. If you want the most negative possible number, you don't need a separate constant, you can just use -(Number.MAX_VALUE), as 754 reals are signed-magnitude.
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.
=== 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.
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.
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.
new String("foo") === new String("foo") is false. === does not mean value and type are equal, it means that the left is the same object as on the right OR that both the left and right are primitives with the same value.
The behavior there is a result of the 'new' operator. typeof new String("foo") is specified to be "object", and it is extensible (String("foo") is not). Both == and === on two object-types return true if both refer to the same thing. More generally, when two types are the same, == has the same behavior as ===.
`===` means that javascript does a normal equality test, whether it be string comparison or numerical comparison, but without any type conversion. It means that while `"3" == 3` is `true` when you execute `"3" === 3"` it is false.
Given two `NaN`s, it would see they're both floats, do a floating point comparison, and return `false`. As it should.
"== - 'values are equal' - in this case, are these two numbers equal? The IEEE spec would say no."
"=== - ...are both the values and types..."
If the values are not equal, how can both the values and types be?
Looking at the ECMAScript 5 standard even if you take out the explicit handling of NaN in the === (Strict Equality) definition it should still evaluate to false since the next subrule compares the numeric value.
4.If Type(x) is Number, then
a.If x is NaN, return false.
b.If y is NaN, return false.
c.If x is the same Number value as y, return true.
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"?
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?
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.
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.
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.
The people writing the JavaScript that demonstrates the wtf.
I can see that some of the design decisions in IEEE-754, like NaN not beeing equal to NaN might seem unintuitive, but it has nothing to do with JavaScript - the standard is implemented by numerous languages and hardware.
That large numbers are rounded to a limited precision should not even be wtf if you think about it for a moment. Otherwise a single use of PI would fill up all the computer memory.
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.
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.
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").
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
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?).
>(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:
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.
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.
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 ;).
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.")
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.
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.
Ah. I don't know the inner workings of Javascript so I'm not surprised I was wrong. Just at a glance, that problem to me screams floating point limitation.
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.