Below is a pure function f
for which f(a) !== f(b)
despite a === b
(notice the strict equalities) for some values of a
and b
:
var f = function (x) {
return 1 / x;
}
+0 === -0 // true
f(+0) === f(-0) // false
The existence of such functions can lead to difficult-to-find bugs. Are there other examples I should be weary of?
1/+0
is Infinity and1/-0
-Infinity, while +0 === -0.This can be explained by the fact that ECMA defines -0 to equal +0 as a special case, while in other operations these two values retain their different properties, which result in some inconsistencies.
This is only possible because the language explicitly defines two non-equal values to be equal, that in fact are not.
Other examples, if any, should be based on the same sort of artificial equality, and given http://ecma262-5.com/ELS5_HTML.htm#Section_11.9.6 there is no other such excention, so probably no other example of this.
If it's of any use, we can ensure that
0
is not-0
by adding0
to it:I'm not so sure this is so scary ;-) Javascript is not a pure language and the presence of +/-0 and the equality of -0 and +0 are specific to IEEE-754 and are "well defined", even if perhaps sometimes surprising. (Even NaN != NaN always being true is well defined, for instance.)
From signed zero:
Technically, because the two inputs to
f
are different, then the result can also be different. For what it's worth, Haskell will treat0 == -0
as true but will treat(1 / 0) == (1 / (-0))
as false.However, I do find this an interesting question.
Happy coding.
In ECMAScript 3, another example where
===
behaves surprisingly is with joined functions. Consider a case like this:An implementation is allowed to "join" the two functions (see §13.2 of the spec), and if it does so, then
oneReturner === twoReturner
will betrue
(see §13.1.2), even though the two functions do different things. Similarly with these:Here an implementation can say that
myAlert === console.myLog
, even thoughmyAlert
is actually equivalent toalert
andconsole.myLog
is actually equivalent toconsole.log
.(However, this aspect of ECMAScript 3 was not preserved in ECMAScript 5: functions are no longer allowed to be joined.)
this behaviour is perfectly ok, because, in mathematical theory,
-0 === +0
is true, and1/(-0) === 1/(+0)
is not, because-inf != +inf
EDIT: although I am really surprised that javascript can in fact handle these kinds of mathematical concepts.
EDIT2: additionally, the phenomenon you described is completely based on the fact, that you divide by zero from which you should expect at least some strange behaviour.
Yes, because
NaN !== NaN
.Some other examples that yield
NaN
whose arguments can be strictly equal:There are many such functions, here is another example
1 == "1" but f(1) != f("1")
This is because equality is a nuanced concept.
Perhaps more scary is that in your example -0 === +0.