Comparing two values in any language is the most used operations. In many cases you may need to compare different variables values, that is the reason in many JavaScript code you will find the following lines:
if (age == years) { // do something here }
or JavaScript which follows best practices, you will find:
if (age === years) { // do something here }
Operation in the first example is also called "lenient" or "normal" equality while the latter one is also called “strict” or “identical” equality.
Why different operator?
When a comparison is made using a double-equals operator, it will check the values of a variable and convert them to a common type and returns true if both are equals. So comparing number with a string having the same value will return true.
JavaScript supports different data types which includes string, number, booleans, array, object, function, null and undefined. When comparing different types with double equals operator an implicit conversion is occurring and then the comparison is made. This conversion is made for boolean to a number when comparing numbers with boolean, or number to string when comparing string with numbers.
This conversion not only an overhead but also give unexpected(wrong) output in many cases.
Here are some examples:
console.log(23 == "23"); // true console.log(1 == true); // true
Some programmers find it useful that auto-conversion is making it easy to compare, but it is not always the case. It may cause serious issues.
For example:
console.log(' \r\t\n' == 0); // true console.log(0 == ' '); // true
Here in these cases space is converted to false or zero which causing the result true in both above cases. Which may cause your comparison to going in wrong directions.
That is the reason most of the JavaScript expert programmers use and recommend triple-equals operator instead of the double-equals operator.
As Douglas Crockford's stated in his book JavaScript: The Good Parts:
JavaScript has two sets of equality operators: === and !==, and their evil twins == and !=. The good ones work the way you would expect. If the two operands are of the same type and have the same value, then === produces true and !== produces false. The evil twins do the right thing when the operands are of the same type, but if they are of different types, they attempt to coerce the values. the rules by which they do that are complicated and unmemorable. These are some of the interesting cases:
'' == '0' // returns false 0 == '' // returns true 0 == '0' // returns true false == 'false' // returns false false == '0' // returns true false == undefined // returns false false == null // returns false null == undefined // returns true ' \t\r\n ' == 0 // returns true
In contrast to double equals operator, another operator with three equals not made the implicit conversion so it not only compare values but also the type of variable that's why it is also called strict comparison.
Due to not implicit conversion, it is not only better in performance but guarantees the correct results always.
Here are examples:
console.log(23 === "23"); // returns false console.log(1 === true); // returns false console.log(' \t\r\n' === 0); // returns false console.log(0 === ' '); // returns false
Not-Equals to Operator?
Same situation or output is return when not-equals to comparison is made between two variables using != or !== operators
Here are examples:
console.log(23 != "23"); // false console.log(1 != true); // false console.log(' \t\r\n' != 0); // false console.log(0 != ' '); // false
As expected result should be true from the above comparison but due to implicit conversion, all comparison returns true.
To make it work correctly use !== operator:
console.log(23 !== "23"); // true console.log(1 !== true); // true console.log(' \t\r\n' !== 0); // true console.log(0 !== ' '); // true
Comparison in Reference Types
When comparing non-primitive data types (reference types) both operators behave consistent (except in some cases discussed below)
Here are some example:
var arrayOne = [1,2,3]; var arrayTwo = [1,2,3]; var objectOne = { x: 1, y: 2 }; var objectTwo = { x: 1, y: 2 }; arrayOne == arrayTwo // false arrayOne === arrayTwo // false objectOne == objectTwo // false objectOne === objectTwo // falseA special case is the one when you comparing primitive type with an object that returns the same primitive type due to valueOf or toString methods. The special cases include comparing primitive string compare to new String() object or primitive number compare with a new Number() object or same for boolean.
Here are examples:
new String("abc") == "abc" // returns true new String("abc") === "abc" // returns false
Here triple equals operator returned false as it matches types of both sides which are string and object. while double equals operator returned true it matches value after conversion.
Performance Comparison
When comparing two variables of the same data type, both operator takes almost equal time. But if the type is not the same triple equals operator will be faster because it would not try to convert the types of variable causing it sooner to exit than double equals operator.
Here another point to notice is that the triple equals operator has one extra character, so using it might increase the JavaScript file size which may take the time to load but this is negligible.
Performance Test of both operator with same and different data types.
So, I may conclude it by recommending always to use triple equals operators, which may sometime make you to do explicit conversion but it prevent from unexpected and wrong output. It is one best practice recommend by many JavaScript experts. Like Douglas Crockford's says:
The lack of transitivity is alarming. My advice is to never use the evil twins. Instead, always use === and !==.
Good stuff man!
ReplyDeleteThe greatness in the blog is your way of explanation and effort behind it .. Thanks mate
ReplyDeleteGreat blog.. very simple, to the point and basic explanation... having been a teacher and a writer, I know how touch it is to write such content.. and that quote from the book is the icing on the cake that is this article :)
ReplyDeleteYour research is good but I disagree with the conclusion you draw - I wouldn't say that you should "always" use === over ==. Type coercion may comfort the lazy for the short term, but its rules can also make good sense when looking at parsing user input. false == "\n "; being true can be reasonable if a field has any displayable text, for example. I'd say === should be your default, and only use == if you're sure it makes sense in the context you're using it.
ReplyDeleteYep. Well stated and probably the best advice for usage
Deletethanks. very useful
ReplyDeleteThank you!
ReplyDeleteNice one :)
ReplyDeletewow... lazy interviewers from 2008 called. They want their explaination back.
ReplyDeletetake it from me. the user experience will not suffer between == and ===. usually it is because newbs use js to traverse the DOM
I thought it was just an old standard. thank you for a very clear explanation..
ReplyDeletejust learning JavaScript now..
This is great
ReplyDeleteI agree with others. Great article here. Was wondering about the === and didn't realize that there was a !==. Boy, many training courses could use this info.
ReplyDeleteThere is a typo in the first word of second para of Performance Comparison.
ReplyDeleteGreat posting ! Really informative.Thank's
ReplyDelete