I'm just starting and really confused. Thanks!
Videos
The strict equality operator (===) behaves identically to the abstract equality operator (==) except no type conversion is done, and the types must be the same to be considered equal.
Reference: JavaScript Tutorial: Comparison Operators
The == operator will compare for equality after doing any necessary type conversions. The === operator will not do the conversion, so if two values are not the same type === will simply return false. Both are equally quick.
To quote Douglas Crockford's excellent 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===producestrueand!==producesfalse. 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' // false 0 == '' // true 0 == '0' // true
false == 'false' // false false == '0' // true
false == undefined // false false == null // false null == undefined // true
' \t\r\n ' == 0 // true

The lack of transitivity is alarming. My advice is to never use the evil twins. Instead, always use
===and!==. All of the comparisons just shown producefalsewith the===operator.
Update
A good point was brought up by @Casebash in the comments and in @Phillipe Laybaert's answer concerning objects. For objects, == and === act consistently with one another (except in a special case).
var a = [1,2,3];
var b = [1,2,3];
var c = { x: 1, y: 2 };
var d = { x: 1, y: 2 };
var e = "text";
var f = "te" + "xt";
a == b // false
a === b // false
c == d // false
c === d // false
e == f // true
e === f // true
The special case is when you compare a primitive with an object that evaluates to the same primitive, due to its toString or valueOf method. For example, consider the comparison of a string primitive with a string object created using the String constructor.
"abc" == new String("abc") // true
"abc" === new String("abc") // false
Here the == operator is checking the values of the two objects and returning true, but the === is seeing that they're not the same type and returning false. Which one is correct? That really depends on what you're trying to compare. My advice is to bypass the question entirely and just don't use the String constructor to create string objects from string literals.
Reference
https://262.ecma-international.org/5.1/#sec-11.9.3
Using the == operator (Equality)
true == 1; //true, because 'true' is converted to 1 and then compared
"2" == 2; //true, because "2" is converted to 2 and then compared
Using the === operator (Identity)
true === 1; //false
"2" === 2; //false
This is because the equality operator == does type coercion, meaning that the interpreter implicitly tries to convert the values before comparing.
On the other hand, the identity operator === does not do type coercion, and thus does not convert the values when comparing.
I have been writing JS for a while now but I still don’t feel like I have encountered any use cases where the equality operator should be used instead of the identity operator. It feels like if you need to do type coercion prior to comparing values that might be indicative of a design flaw in the system, but I’d like to know legitimate use cases where the equality operator makes more sense. Thanks!
We're having a discussion at work over whether we should default to `===` or `==` while using typescript.
Opinions seem to be dependent on whether we came from a javascript background or a c# background.
There's a discussion on this stackoverflow discussing for and against. I'd never really considered deviating from the `===` since it's what was always reinforced as best practice in javascript. But some are arguing that it's largely unnecessary thanks to typescript's type checking:
Your intuition was correct,
===adds little value in TypeScript. The argument about "compilation to JS" is not really valid. TS ensures both operands have the same type. And when both operands have the same type==and===behave identically. For example: ...
I'm going to make an argument for ==
Douglas Crockford which you cited is known for his many and often very useful opinions. While I'm with Crockford in this particular case it's worth mentioning it is not the only opinion. There are others like language creator Brendan Eich who don't see the big problem with ==. The argument goes a little like the following:
JavaScript is a behaviorally* typed language. Things are treated based on what they can do and not their actual type. This is why you can call an array's .map method on a NodeList or on a jQuery selection set. It's also why you can do 3 - "5" and get something meaningful back - because "5" can act like a number.
When you perform a == equality you are comparing the contents of a variable rather than its type. Here are some cases where this is useful:
- Reading a number from the user - read the
.valueof an input element in the DOM? No problem! You don't have to start casting it or worrying about its type - you can==it right away to numbers and get something meaningful back. - Need to check for the "existence" of a declared variable? - you can
== nullit since behaviorallynullrepresents there is nothing there andundefineddoesn't have anything there either. - Need to check if you got meaningful input from a user? - check if the input is
falsewith the==argument, it will treat cases the user has entered nothing or just white-space for you which is probably what you need.
Let's look at Crockford's examples and explain them behaviorally:
'' == '0' // got input from user vs. didn't get input - so false
0 == '' // number representing empty and string representing empty - so true
0 == '0' // these both behave as the number 0 when added to numbers - so true
false == 'false' // false vs got input from user which is truthy - so false
false == '0' // both can substitute for 0 as numbers - so again true
false == undefined // having nothing is not the same as having a false value - so false
false == null // having empty is not the same as having a false value - so false
null == undefined // both don't represent a value - so true
' \t\r\n ' == 0 // didn't get meaningful input from user vs falsey number - true
Basically, == is designed to work based on how primitives behave in JavaScript, not based on what they are. While I don't personally agree with this point of view there is definitely merit in doing it - especially if you take this paradigm of treating types based on behavior language-wide.
* some might prefer the name structural typing which is more common but there is a difference - not really interested in discussing the difference here.
It turns out that jQuery uses the construct
if (someObj == null) {
// do something
}
extensively, as a shorthand for the equivalent code:
if ((someObj === undefined) || (someObj === null)) {
// do something
}
This is a consequence of the ECMAScript Language Specification § 11.9.3, The Abstract Equality Comparison Algorithm, which states, among other things, that
1. If Type(x) is the same as Type(y), then
a. If Type(x) is Undefined, return true.
b. If Type(x) is Null, return true.
and
2. If x is null and y is undefined, return true.
3. If x is undefined and y is null, return true.
This particular technique is common enough that JSHint has a flag specifically designed for it.