The double equals (loose equality) operator is an interesting operator. Many avoid it because they don't know how it works. But that's not a good reason to avoid it, a better reason would be knowing how it works, and knowing why you want to avoid it. And then you know why you prefer the triple equals (===) operator for comparisons. Let's get started!

## Double Equals

The double equals operator coerce the operands if their types are not the same, otherwise, it will use the triple equals operator. So, `2 == 3` is the same as `2 === 3` because both `2` and `3` are of the `number` type. But if the types are not the same, JavaScript will try to coerce either one or both of the operands. For example, if you compare `2 == "3"`, you are comparing number 2 with a string whose value is 3. In this case, JavaScript will coerce string 3 to number 3, and then it will call `2 === 3` which will result false.

Now, that we know the basics of the double equals operator, let's dive deeper and learn how the operator decides what to do.

### The Abstract Equality Comparison

Assume that we are comparing x and y, where x and y could be of any type:

Start: Check if the types are the same. If the types are the same, JavaScript will call triple equals and you are done.

but, if the types are not the same, JavaScript will follow another path. In this path, JavaScript will try to figure out what to coerce. These are the steps it will execute in order:

a. First check if we are comparing `null` and `undefined`. If we are, return true. If not:

b. Check if we are comparing a `string` with a `number`. If we are, coerce the `string` value to number and call the double equals and start over again back to the very first step. Eg:

``````2 == "3"
↓   coerce "3" to number 3.
2 ==  3   calling double equals again, and start over
...
``````

but if we are not:

c. Check if we are comparing a `boolean` with something else. If we are, coerce the `boolean` to a number and call double equals and start over. eg:

``````true == "3"
↓             coerce true to number 1.
1    == "3"   start over again.
...
``````

but if we are not:

d. Check if we are comparing an `object` with a `number`, `string`, or a `symbol`. If we are, coerce the `object` to a primitive, call double equals on the result and start over again. Eg:

``````{ a: 'hello'}      ==     "5"
↓                          coerce the object to a primitive
"[object Object]"  ==     "5"   and start over again
...
``````

another example:

``````[1,2,3]     ==     "5"
↓                       coerce object to a primitive
"1,2,3"     ==     "5"    and start over again
...
``````

(I'll explain how the objects get coerced to primitives in a second, but for now bare with me.)

If not, we don't have anything else to check. If none of the steps above matches, return false at the end.

Here is the complete picture: You can click the image to see the larger version.

## Abstract Operators:

### Coercing Objects to Primitives

I promised you to explain to you how objects get coerced to primitives. This is how it works:

First by default, call the `valueOf` method of the object. If `valueOf` returns a primitive, use that.

Otherwise call the `toString` method of the object. If `toString` returns a primitive, use that

otherwise throw an error.

Note 1: These steps happen by default. If it is hinted to prefer `string`, JavaScript will call `toString` first, and then `valueOf`. By default JavaScript is hinted to prefer `number`, so it will call `valueOf` first, and then `toString`.

Note 2: When coercing a `Date` object to a primitive, JavaScript is hinted to prefer `string`. So it will call `toString` first and then `valueOf`. In all the other cases, the default preferred type hint is `number`.

Let's look at some examples:

Example 1:

``````// coercing an empty object to a primitive
var x = {};
x.valueOf();   // -> {} : not a primitive, call toString now.
x.toString();  // -> "[object Object]": string is a primitive, I like it!
``````

In the example above, when `x` is coerced to a primitive, the result would be the funny looking string: `"[object Object]"`

Example 2:

``````// coercing an object with custom `valueOf`
var x = {name: 'Tom'};
x.valueOf = function () {return 5;};
x.valueOf();   // -> 5 : number primitive, I liked it!
``````

In the example above, when `x` is coerced to a primitive, the result would be the number 5.

Example 3:

``````// coercing an array of numbers to a primitive
var x = [1,2,3];
x.valueOf();   // -> [1,2,3] : not a primitive, call toString now.
x.toString();  // -> "1,2,3" : string is a primitive, I like it!
``````

In the example above, when `x` is coerced to a primitive, the result would be the string: `"1,2,3"`

Example 4:

``````// coercing an array of elements with different types to a primitive
var x = [undefined, null, true, 1, "5", new Date(), {a: 2}, [1,2,3]]
x.valueOf();   // -> Array itself : not a primitive, call toString now.
x.toString();  // -> ",,true,1,5,Sat Mar 05 2016 10:59:47 GMT-0500 (EST),[object Object],1,2,3" : string is a primitive, I like it!
``````

In the example above, when `x` is coerced to a primitive, the result would be the string: `",,true,1,5,Sat Mar 05 2016 10:59:47 GMT-0500 (EST),[object Object],1,2,3"`

### Coercing to `number`: `ToNumber(input)`

The following summarizes what `ToNumber` does for different input types:

• `undefined``NaN`
• `null``0`
• `number` → return the number itself
• `boolean``0` if input is `false`, `1` if input is `true`
• `string` → parse string, if string is a number return number, otherwise return `NaN`. Empty string returns `0`.

Eg: `"5"``5`, `""` → 0, `"29xY"``NaN`

• `object`: call `ToPrimitive` first, then call `ToNumber` on the result of `ToPrimitive`. See the `toPrimitive` section to learn how objects get coerced to primitives
`Date` → calls `getTime()` method and returns the value

### Coercing to `string`: `ToString(input)`

The following summarizes what `ToNumber` does for different input types:

• `undefined``"undefined"`
• `null``"null"`
• `number` → "number"
• `boolean` → "true", "false"
• `string` → return the string itself.
• `object`: call `ToPrimitive` first with a hint of `string`, then call `ToString` on the result of `ToPrimitive`. See the `toPrimitive` section to learn how objects get coerced to primitives
`Date` → calls `toString()` method and returns the value

### Coercing to `boolean`: `ToBoolean(input)`

In JavaScript, the following values are falsy:

• `undefined`
• `null`
• `0`
• `""`
• `NaN`

Everything else is truthy. Knowing this fact will make it easy to know what happens after a value is coerced to a boolean:

• `undefined``false`
• `null``false`
• `number``false` if 0, otherwise, `true`
• `boolean` → input iteself
• `string``false` if empty string `""`, otherwise `true`
• `object``true`. This follows that `array``true`
• `Date``true`

## Double Equals Examples

Now that we know how double equals work, we can have some fun and look at some examples. I am going to explain what path does JavaScript take to decide what to output.

Example: `[] == 0`

a. Are types different? yes, so we have to take the long path:
b. Are we comparing `null` with `undefined`? no, go to next check:
c. Are we comparing a `number` with a `string`? no, go to next check:
d. Are we comparing a `boolean` with something else? no, go to the next check:

e. Are we comparing an `object` with a `number` or `string`, or `symbol`? YES! we are comparing the array object with a number. Ok, let's coerce the array to a primitive and call double equals again:

• calling `valueOf` on the array: output is `[]`, which is not a primitive and I can't use it. Let's call `toString`:
• calling `toString` on the array: output is `""`. Perfect it is a primitive string, and I can use it.

Calling double equals again with the result of coercing the object to a primitive:

`"" == 0`

And now we go back to the beginning and start over again:

a. Are the types the same? no, take the long path:
b. Are we comparing `null` with `undefined`? no, go to next check:
c. Are we comparing a `number` with a `string`? YES, now let's coerce the string to a number. coercing the empty string to a number will return `0`. Call double equals again and start over:

`0 == 0`

a. Are the types the same? Yes, call triple equals `0 === 0` and the result is true

So in summary:

``````[] == 0
↓
"" == 0
↓
0 == 0
↓
0 === 0
→ true
``````

Let's keep this example in mind and look at some other examples. In the following examples, I will it to you to go through the whole algorithm.

Example: `[] == "0"`

``````[] == "0"
↓
"" == "0"
↓
"" === "0"
→ false
``````

Example: `false == 1`

``````false == 1
↓
0 == 1
↓
0 === 1
→ false
``````

Example: `{} == false`

```javascript {} == false ↓ {} == 0 ↓ "[object Object]" == 0 ↓ NaN == 0 ↓ NaN === 0 → false ```

Example: `undefined == false`

``````undefined == false
↓
undefined == 0
→ false
``````

Example: `[1,2,3] == 123`:

``````[1,2,3] == 123
↓
"1,2,3" == 123
↓
NaN    ==  123
↓
NaN   ===  123
↓
→ false
``````

Example: ` == 123`:

`````` == 123
↓
"123" == 123
↓
123    ==  123
↓
123   ===  123
↓
→ true
``````

Example: ` == "123"`:

`````` == "123"
↓
"123" == "123"
↓
"123" === "123"
↓
→ true
``````

For the following examples, `x` is defined as the following:

``````var x = {
a: '...',
toString: function () {
return false;
},
valueOf: function () {
return new Boolean(true);
}
};
``````

Example: `x == "0"`:

``````x == "0"
↓
false == "0"
↓
0    ==  "0"
↓
0    ==  0
↓
0   === 0
↓
→ true
``````

Example: `x == 5`:

``````x == 5
↓
false == 5
↓
0    ==  5
↓
0   ===  5
→ false
``````

Example: `x == [1,2,3]`:

``````x == [1,2,3] // both are objects
↓
x === [1,2,3] // they are stored at different addresses
→ false // the address is not the same
``````