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?
Yes, because NaN !== NaN.
var f = function (x) { return Infinity - x; }
Infinity === Infinity // true
f(Infinity) === f(Infinity) // false
f(Infinity) // NaN
Some other examples that yield NaN whose arguments can be strictly equal:
0/0
Infinity/Infinity
Infinity*0
Math.sqrt(-1)
Math.log(-1)
Math.asin(-2)
this behaviour is perfectly ok, because, in mathematical theory, -0 === +0 is true, and 1/(-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.
1/+0 is Infinity and 1/-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 adding 0 to it:
var f = function(x) {
return 1 / (x + 0);
}
f(+0) === f(-0)
In ECMAScript 3, another example where === behaves surprisingly is with joined functions. Consider a case like this:
function createConstantFunction(result) {
return function () {
return result;
};
}
var oneReturner = createConstantFunction(1); // a function that always returns 1
var twoReturner = createConstantFunction(2); // a function that always returns 2
An implementation is allowed to "join" the two functions (see §13.2 of the spec), and if it does so, then oneReturner === twoReturner will be true (see §13.1.2), even though the two functions do different things. Similarly with these:
// a perfect forwarder: returns a sort of "duplicate" of its argument
function duplicateFunction(f) {
return function (f) {
return f.apply(this, arguments);
};
}
var myAlert = duplicateFunction(alert);
console.myLog = duplicateFunction(console.log);
Here an implementation can say that myAlert === console.myLog, even though myAlert is actually equivalent to alert and console.myLog is actually equivalent to console.log.
(However, this aspect of ECMAScript 3 was not preserved in ECMAScript 5: functions are no longer allowed to be joined.)
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:
According to the IEEE 754 standard, negative zero and positive zero should compare as equal with the usual (numerical) comparison operators...
Technically, because the two inputs to f are different, then the result can also be different. For what it's worth, Haskell will treat 0 == -0 as true but will treat (1 / 0) == (1 / (-0)) as false.
However, I do find this an interesting question.
Happy coding.
There are many such functions, here is another example
function f (a) {
return a + 1;
}
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.
Related
What is a simple construction for a greater than OR equal where the equal part is only applied based on a boolean parameter.
A straightforward way (Type(Java)Script):
function isGreaterThanOrEqual(a: number, b:number, allowEqual: boolean = false): boolean {
if(allowEqual){
return a >= b;
} else {
return a > b
}
}
I have a (rotated) rectangle collision detection method in which numerous of these comparisons are made. Sometimes I want to include rectangles touching each other and sometimes not (they must "really" overlap) that's why this optional allowEqual parameter comes in handy.
I would like to prevent to have this if statement at numerous places in this method and prefer an elegant one-liner.
Can this be done in a one-liner in any way?
You could use a staged approach by returning either the value of the greater check or check allowEqual and the identity check.
return a > b || allowEqual && a === b;
return (a - b) >= (+(!allowEqual)) * Number.EPSILON;
Explained:
If allowEqual is true, its negation is coerced to 0, so a - b has to be at least 0. If allowEqual is false, its negation is coerced to 1, so a - b has to be at least the smallest possible distance between two numbers.
Say I have the following objects in Javascript:
var a = { xxx: 33 };
var b = { xxx: 33 };
var c;
c = a;
What is the Javascript test that will tell me whether I am dealing with the same object instance? In other words, it should return false for a and b, b and c, but true for a and c.
You just need this
if(c == a) {
// same instance
}
a == b and b == c will return false
Just a standard equality test:
( a == c ) // true
( a == b ) // false
I know the question is about checking if two objects are the same instance but this thread will not be complete without the following.
If you are after checking whether 2 objects are the same, a double equal == is enough. However, for value types (primitives), you may be in a for surprise. Check out the following:
var a = 1; // Integer 1
var b = '1' // String '1'
if (a == b) console.log('Same.');
else console.log('Not same.');
Above will print Same.. To avoid that, use the triple equal === which means two things:
Are they the same value?
Are they the same type?
Or you can use Object.is method like Object.is(a, b).
if (a === b) console.log('Same.');
else console.log('Not same.');
if (Object.is(a, b)) console.log('Same for Object.is.');
else console.log('Not same for Object.is.');
Above will print Not same. and Not same for Object.is..
Some More Info
Below is some more information which has been copy/pasted from this article:
Which operation you choose depends on what sort of comparison you are looking to perform. Briefly:
double equals (==) will perform a type conversion when comparing two things, and will handle NaN, -0, and +0 specially to conform to IEEE 754 (so NaN != NaN, and -0 == +0);
triple equals (===) will do the same comparison as double equals (including the special handling for NaN, -0, and +0) but without type conversion; if the types differ, false is returned.
Object.is does no type conversion and no special handling for NaN, -0, and +0 (giving it the same behavior as === except on those special numeric values).
Note that the distinction between these all have to do with their handling of primitives; none of them compares whether the parameters are conceptually similar in structure. For any non-primitive objects x and y which have the same structure but are distinct objects themselves, all of the above forms will evaluate to false.
Conclusion
My two cents on this would be to get into the habit of always using triple equals === because it cannot hurt you but double equals == can indeed hurt you. You may use double equals == when you just care about the value and the thing you are comparing are primitives; but even this is discouraged because it mostly means a flaw in design. Languages like TypeScript will even avoid that i.e. comparing a '1' to 1 without being explicit about it.
The following are examples that make sense to me.
isFinite(5) // true - makes sense to me, it is a number and it is finite
typeof 5 // "number"
isFinite(Infinity) // false - makes sense for logical reasons
typeof Infinity // "number"
isFinite(document) // false - makes sense as well, it's not even a number
typeof document // "object"
The following is where I get confused.
isFinite(null) // true - Wait what? Other non-number objects returned false. I see no reason?
typeof null // "object"
I just don't see the reasoning behind this.
What I'd like is the most low-level answer possible.
I think null is being converted to 0, why? What other impacts does this have?
The ECMAScript spec (5.1) defines isFinite to act as such:
isFinite (number)
Returns false if the argument coerces to NaN, +∞, or −∞, and otherwise returns true.
If ToNumber(number) is NaN, +∞, or −∞, return false.
Otherwise, return true.
In other words, isFinite is calling ToNumber on whatever's passed in, and then comparing it to either pos/neg infinity or NaN.
In JavaScript (note the use of != instead of the more common !==, causing the type cast):
function isFinite(someInput) {
return !isNaN(someInput) &&
someInput != Number.POSITIVE_INFINITY &&
someInput != Number.NEGATIVE_INFINITY;
}
(As noted in the comments below, someInput != NaN is not needed, as NaN is defined to not be equivalent to everything, including itself.)
Now, why is null converted to zero (as opposed to undefined)? As TylerH says in the comments, null means that a value exists, but is empty. The mathematical representation of this is 0. undefined means that there isn't a value there, so we get NaN when trying to call ToNumber on it.
http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.5
However, ECMAScript 6 is bringing along a non-converting isFinite as a property of Number. Douglas Crockford suggested it here: http://wiki.ecmascript.org/doku.php?id=harmony:number.isfinite
From MDN:
The global isFinite() function determines whether the passed value is
a finite number. If needed, the parameter is first converted to a
number.
So, it's converted to a number...
isFinite(null)
isFinite(+null) //convert to a number
isFinite(0) // true because +null or Number(null) = 0
The spec says that the global isFinite() method will forcibly convert the parameter to a number.
You could, however, use (at your own risk) the EcmaScript 6 spec's Number.isFinite() which doesn't perform this conversion.
Number.isFinite(null) // false
Or, like lodash and underscore do it...
var _.isFinite = function(obj) {
return isFinite(obj) && !isNaN(parseFloat(obj));
};
isFinite calls ToNumber on its argument. So
> Number(null)
0
> Number(document)
NaN
> isFinite(0)
true
> isFinite(NaN)
false
> isFinite(null)
true
> isFinite(document)
false
Because, if you say
Number(null) === 0 which is finite
See To Number Conversions
Which says that, for argument type null result is +0
isFinite typecasts it's argument to a number, if it's not already a number. Essentially you have isFinite(Number(null)) and Number(null) === 0. Which is finite.
Beside null, you find these examples interesting too:
alert(isFinite(' ')); //true
alert(isFinite('')); //true
alert(isFinite(null)); //true
alert(isFinite(!undefined)); //true
In JavaScript implicit conversion take place, This conversion try to convert bool to integer when comparing numbers with boolean, or number to string when comparing string with numbers. If you treat any data-type as number it implicitly converted to number so all above cases return zero which is finite. See Here
If you try Number(undefined) it give you a NaN on negate this would produce a 1 which is finite.
In Javascript:
NaN === NaN; // false
I was trying to determine when isNaN(foo) is not just equivalent to +foo "is" NaN. But I don't know how to tell if something is NaN except by using isNaN, which says yes for many things, none of which === NaN.
So I think the right way to do this would be to work around other possibilities:
typeof NaN === 'number' // true
Therefore I think
typeof(foo) === 'number' && isNaN(foo)
Is the closest to what I am thinking of. It makes sense since it makes sense that NaN would be the only number that isn't a number, or something. Is this correct, and is this the best way?
Use that to your advantage:
foo !== foo
This is equivalent to typeof foo === 'number' && isNaN(foo), and is what Underscore.js uses to check for exactly NaN, too.
The reason that NaN isn't equal to itself is that two calculations can become NaN for different reasons. If you do two calculations and compare the results, you don't want them to be equal if one of the values are NaN, or both of them.
The isNaN method works fine as long as you only use it on numerical values. It gives unintuitive results for a lot of other types, so you simply shouldn't use it on anything other than numbers.
If you can use ECMAScript 6, you have Object.is:
return Object.is(foo, NaN);
Object.is() determines whether two values are the same value. Two values are the same if one of the following holds:
[...]
both NaN
MDN also suggests a Polyfill if Object.is isn't defined (uses the same foo!==foo trick):
if (!Object.is) {
Object.is = function(x, y) {
// SameValue algorithm
if (x === y) { // Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return x !== 0 || 1 / x === 1 / y;
} else {
// Step 6.a: NaN == NaN
return x !== x && y !== y;
}
};
}
In javascript, when using an if statement with multiple conditions to test for, does javascript test them all regardless, or will it bail before testing them all if it's already false?
For example:
a = 1
b = 2
c = 1
if (a==1 && b==1 && c==1)
Will javascript test for all 3 of those conditions or, after seeing that b does not equal 1, and is therefore false, will it exit the statement?
I ask from a performance standpoint. If, for instance, I'm testing 3 complex jQuery selectors I'd rather not have jQuery traverse the DOM 3 times if it's obvious via the first one that it's going to return FALSE. (In which case it'd make more sense to nest 3 if statements).
ADDENDUM: More of a curiosity, what is the proper term for this? I notice that many of you use the term 'short circuit'. Also, do some languages do this and others dont?
The && operator "short-circuits" - that is, if the left condition is false, it doesn't bother evaluating the right one.
Similarly, the || operator short-circuits if the left condition is true.
EDIT: Though, you shouldn't worry about performance until you've benchmarked and determined that it's a problem. Premature micro-optimization is the bane of maintainability.
From a performance standpoint, this is not a micro-optimization.
If we have 3 Boolean variables, a, b, c that is a micro-optimization.
If we call 3 functions that return Boolean variables, each function may take a long time, and not only is it important to know this short circuits, but in what order. For example:
if (takesSeconds() && takesMinutes())
is much better than
if (takesMinutes() && takesSeconds())
if both are equally likely to return false.
That's why you can do in javascript code like
var x = x || 2;
Which would mean that if x is undefined or otherwise 'false' then the default value is 2.
In case someone's wondering if there is a way to force the evaluation of all condition, in some cases the bitwise operators & and | can be used
var testOr = true | alert(""); //alert pops up
var testAnd = false & alert(""); //alert pops up
These should be used really carefully because bitwise operators are arithmetic operators that works on single bits of their operand and can't always function as "non short-circuit" version of && and ||
Example:
-2147483648 && 1 = 1
but
-2147483648 & 1 = 0
Hope it helps someone who arrived here looking for information like this (like me) and thanks to #Max for the correction and the counter-example
It will only test all the conditions if the first ones are true, test it for yourself:
javascript: alert (false && alert("A") && false);
It short circuits - only a and b will be compared in your example.
Another reason why stopping evaluation with 1 or more parameters to the left.
if (response.authResponse && (response.authResponse.accessToken != user.accessToken)){
...
}
the second evaluation relies on the first being true and won't throw a compile error if response.authResponse is null or undefined etc because the first condition failed.
Other languages had this problem in the early days and I think it's a standard approach in building compilers now.
It exits after seeing that b does not equal one.
For anyone on this question confused because they're not seeing the short-circuit behaviour when using an || in conjunction with an ? operator like so:
x = 1 || true ? 2 : 3 // value of x will be 2, rather than 1 as expected
it seems like the short circuit rule isn't working. Why is it evaluating the second term of the || (true ? 2 : 3) when the first is true? It turns out to be an order of operations problem because the above is the equivalent of
x = (1 || true) ? 2 : 3
with the || evaluated first and the ? evaluated second. What you likely want is:
x = 1 || (true ? 2 : 3)
For this case:
a = 1
b = 2
c = 1
if (a==1 && b==1 && c==1)
You can use:
if ([a, b, c].every(x => x == 1))
// do something if a, b and c are equal to 1.
If you want to know if at least one is equal to 1, use the some() method instead of every():
if ([a, b, c].some(x => x == 1))
// do something if a, b or c is equal to 1.
every() and some() are array methods.