Equality

原文链接:http://dailyjs.com/post/equality

There are four equality operators in JavaScript:

  • Equals: ==
  • Not equal: !=
  • Strict equal: ===
  • Strict not equal: !==

In JavaScript: The Good Parts, Douglas Crockford advises against using == and !=:

My advice is to never use the evil twins. Instead, always use === and !==.

The result of the equals operator is calculated based on The Abstract Equality Comparison Algorithm. This can lead to confusing results, and these examples are often cited:

'' == '0'           // false
0 == ''             // true
0 == '0'            // true

false == undefined  // false
false == null       // false
null == undefined   // true

Fortunately, we can look at the algorithm to better understand these results. The first example is false due to this rule:

If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions). Otherwise, return false.

Basically, the sequence of strings is not the same. In the second example, the types are different, so this rule is used:

If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).

This is where the behaviour of the == starts to get seriously gnarly: behind the scenes, values and objects are changed to different types. The equality operator always tries to compare primitive values, whereas the strict equality operator will return false if the two values are not the same type. For reference, the underlying mechanism used by the strict equality operator is documented in the The Strict Equality Comparison Algorithm section in the ECMAScript Specification.

Strict Equality Examples

Using the same example with the strict equality operator shows an arguably more intuitive result:

'' === '0'           // false
0 === ''             // false
0 === '0'            // false

false === undefined  // false
false === null       // false
null === undefined   // false

Is this really how professional JavaScript developers write code? And if so, does === get used that often? Take a look at ajax.js from jQuery's source:

executeOnly = ( structure === prefilters );
if ( typeof selection === "string" ) {
} else if ( params && typeof params === "object" ) {

The strict equality operator is used almost everywhere, apart from here:

if ( s.crossDomain == null ) {

In this case, both undefined and null will be equal, which is a case where == is often used in preference to the strict equivalent:

if ( s.crossDomain === null || s.crossDomain === undefined ) {

Assertions

One place where the difference between equality and strict equality becomes apparent is in JavaScript unit tests. Most assertion libraries include a way to check 'shallow' equality and 'deep equality'. In CommonJS Unit Testing, these are known as assert.equal and assert.deepEqual.

In the case of deepEqual, there's specific handling for dates and arrays:

equivalence is determined by having the same number of owned properties (as verified with Object.prototype.hasOwnProperty.call), the same set of keys (although not necessarily the same order), equivalent values for every corresponding key, and an identical "prototype" property

Conclusion

To understand how equality and strict equality work in JavaScript, primitive values and JavaScript's implicit type conversion behaviour must be understood. In general, experienced developers advocate using ===, and this is good practice for beginners.

In recognising the confusion surrounding these operators, there is a significant amount of documentation on the topic. For example, Comparison Operators in Mozilla's JavaScript Reference.

Fork me on GitHub