I've been reading Douglas Crockford's JavaScript: The Good Parts, and I came across this weird example that doesn't make sense to me:
'' == '0' // false
0 == '' // true
0 == '0' // true
false == undefined // false
false == null // false
null == undefined // true
The author also goes on to mention "to never use ==
and !=
. Instead, always use ===
and !==
". However, he doesn't explain why the above behavior is exhibited? So my question is, why are the above results as they are? Isn't transitivity considered in JavaScript?
'' == '0' // false
The left hand side is an empty string, and the right hand side is a string with one character. They are false because it is making a comparison between two un identical strings (thanks Niall).
0 == '' // true
Hence, why this one is true, because 0
is falsy and the empty string is falsy.
0 == '0' // true
This one is a bit trickier. The spec states that if the operands are a string and a number, then coerce the string to number. '0'
becomes 0
. Thanks smfoote.
false == undefined // false
The value undefined
is special in JavaScript and is not equal to anything else except null
. However, it is falsy.
false == null // false
Again, null
is special. It is only equal to undefined
. It is also falsy.
null == undefined // true
null
and undefined
are similar, but not the same. null
means nothing, whilst undefined
is the value for a variable not set or not existing. It would kind of make sense that their values would be considered equal.
If you want to be really confused, check this...
'\n\r\t' == 0
A string consisting only of whitespace is considered equal to 0.
Douglas Crockford makes a lot of recommendations, but you don't have to take them as gospel. :)
T.J. Crowder makes an excellent suggestion of studying the ECMAScript Language Specification to know the whole story behind these equality tests.
Further Reading?
The spec.
yolpo (on falsy values)
The answer to this question has to do with how JavaScript handles coercion. In the case of ==
, strings are coerced to be numbers. Therefore:
'' == '0'
is equivalent to '' === '0'
(both are strings, so no coercion is necessary).
0 == ''
is equivalent to 0 === 0
because the string ''
becomes the number 0
(math.abs('') === 0
).
0 == '0'
is equivalent to 0 === 0
for the same reason.
false == undefined
is equivalent to 0 === undefined
because JavaScript coerces booleans to be numbers when types don't match
false == null
is equivalent to 0 === null
for the same reason.
null == undefined
is true because the spec says so.
Thanks for asking this question. My understanding of ==
is much better for having researched it.
You can actually write a JavaScript function that behaves exactly like ==
that should give you some insight into how it behaves.
To show you what I mean here is that function:
// loseEqual() behaves just like `==`
function loseEqual(x, y) {
// notice the function only uses "strict" operators
// like `===` and `!==` to do comparisons
if(typeof y === typeof x) return y === x;
if(typeof y === "function" || typeof x === "function") return false;
// treat null and undefined the same
var xIsNothing = (y === undefined) || (y === null);
var yIsNothing = (x === undefined) || (x === null);
if(xIsNothing || yIsNothing) return (xIsNothing && yIsNothing);
if(typeof x === "object") x = toPrimitive(x);
if(typeof y === "object") y = toPrimitive(y);
if(typeof y === typeof x) return y === x;
// convert x and y into numbers if they are not already use the "+" trick
if(typeof x !== "number") x = +x;
if(typeof y !== "number") y = +y;
return x === y;
}
function toPrimitive(obj) {
var value = obj.valueOf();
if(obj !== value) return value;
return obj.toString();
}
As you can see ==
has a lot of complicated logic for type conversion. Because of that it's hard to predict what result you are going to get.
Here are some examples of some results you wouldn't expect:
Unexpected Truths
[1] == true // returns true
'0' == false // returns true
[] == false // returns true
[[]] == false // returns true
[0] == false // returns true
'\r\n\t' == 0 // returns true
Unexpected Conclusions
// IF an empty string '' is equal to the number zero (0)
'' == 0 // return true
// AND the string zero '0' is equal to the number zero (0)
'0' == 0 // return true
// THEN an empty string must be equal to the string zero '0'
'' == '0' // returns **FALSE**
Objects with Special Functions
// Below are examples of objects that
// implement `valueOf()` and `toString()`
var objTest = {
toString: function() {
return "test";
}
};
var obj100 = {
valueOf: function() {
return 100;
}
};
var objTest100 = {
toString: function() {
return "test";
},
valueOf: function() {
return 100;
}
};
objTest == "test" // returns true
obj100 == 100 // returns true
objTest100 == 100 // returns true
objTest100 == "test" // returns **FALSE**
The reason is that identity or strict operator (===), it compares with no type conversion, that means if both values doesn’t have the same value and the same type, they won’t be considered equal.
take a look this link, it takes you out of doubt:
easy way to understand how identity operator works