Equality in JavaScript
Update 2011-12-02: When is it OK to use == in JavaScript?
There are two operators for comparing values in JavaScript: strict equality === and “normal” (or lenient) equality ==. Many style guides (correctly) tell programmers to avoid lenient equality and always use strict equality. This post explains why.
Where appropriate, related sections in the ECMAScript 5 language specification [1] are mentioned in square brackets.
Two ways of comparing
- The strict equality operator === only considers values equal that have the same type.
- The lenient equality operator == tries to convert values of different types, before comparing like strict equality.
Lenient equality causes two problems:
- The conversion rules are counter-intuitive and do things you might not expect.
- As the operator is so forgiving, type errors can remain hidden longer.
Strict equals ===
[ES5 11.9.6] Comparing two values. Values with different types are never equal. If both values have the same type then the following assertions hold.
- undefined === undefined
- null === null
- Two (primitive) numbers:
NaN !== _ // any value including NaN x === x +0 === -0for any number x. Thus equality is not reflexive in JavaScript, because NaN is not equal to itself. - Two booleans, two strings (primitive): obvious results
- Two objects (including arrays and functions): x === y only if x and y are the same object(!). That is, if you want to compare different objects, you have to do it manually.
Examples:
> var a = NaN;
> a === a
false
> var b = {}, c = {};
> b === c
false
> b === b
true
> "abc" === new String("abc")
false // different types (left: primitive, right: object)
Equals ==
[ES5 11.9.3] Comparing two values. If both values have the same type: compare with
===. Otherwise:
- undefined == null
- One number, one string: convert the string to a number
- A boolean and a non-boolean: convert the boolean to a number and then perform the comparison.
- Comparing a string or a number to an object: try to convert the object to a primitive and then make the comparison.
(3) leads to a weird idiosyncrasy where numbers greater than 1 are true in
ifstatements, but not equal to true:
> 0 == false
true
> 1 == true
true
> 2 == true
false
> 2 ? true : false
true // because 2 !== 0
Equality and strings:
> "" == 0
true
> "123" == 123
true
> "" == false
true
> "1" == true
true
> "2" == true
false
> "true" == true
false
> "2" ? true : false
true // because string is non-empty
> "abc" == new String("abc")
true // right side converted to primitive