这两个相等运算符的使用可能会引起一些困惑。
我们来分析一下两者不同

“==” 的比较规则

  1. 先检查两个操作数的数据类型是否相同
  2. 如果相同,则比较两个数是否相等
  3. 如果不同,则先将两个数转换为相同数据类型,再进行比较

我们用表格来分析一下不同类型的值用相等运算符比较后的结果:

类型(x)类型(y)结果
nullundefinedtrue
undefinednulltrue
字符串x == toNumber(y)
字符串toNumber(x) == y
布尔值任何类型toNumber(x) == y
任何类型布尔值x == toNumber(y)
字符串或数对象x == toPrimitive(y)
对象字符串或数toPrimitive(x) == y
  • 如果两个操作数都是对象,则仅当两个操作数都引用同一个对象时才返回true。
  • 如果一个操作数是null,另一个操作数是undefined,则返回true。
  • 如果两个操作数是不同类型的,就会尝试在比较之前将它们转换为相同类型:
    • 当数字与字符串进行比较时,会尝试将字符串转换为数字值。
    • 如果操作数之一是Boolean,则将布尔操作数转换为1或0。
    • 如果操作数之一是对象,另一个是数字或字符串,会尝试使用对象的valueOf()和toString()方法将对象转换为原始值。
  • 如果操作数具有相同的类型,则将它们进行如下比较:
    • String:true仅当两个操作数具有相同顺序的相同字符时才返回。
    • Number:true仅当两个操作数具有相同的值时才返回。+0并被-0视为相同的值。如果任一操作数为NaN,则返回false。
    • Boolean:true仅当操作数为两个true或两个false时才返回true。

toNumber 和 toPrimitive 方法是内部的,并根据以下表格对其估值

toNumber 方法对不同类型返回的结果如下:

值类型结果
undefinedNaN
null+0
布尔值如果是true,返回1;如果是false,返回+0
数对应的值

toPrimitive 方法对不同类型返回的结果如下:

值类型结果
对象如果对象的valueOf方法的结果是返回原始值,返回原始值;如果对象的toString方法返回原始值,就返回这个值;其它情况都返回一个错误

我们可以用例子来验证一下:

例子1:

1
console.log('demo' == true); // false

首先,布尔值会被 toNumber 方法转成数 ,因此得到:demo == 1。
其次,用toNumber 转换字符串值。因为字符串包含字母,所以会被转成NaN,表达式编程了 NaN == 1,结果就是false

例子2

1
console.log('demo' == false); // false

首先,布尔值会被 toNumber 方法转成数 ,因此得到:demo == 0。
其次,用toNumber 转换字符串值。因为字符串包含字母,所以会被转成NaN,表达式编程了 NaN == 0,结果就是false

“===”的比较规则

  1. 先检查两个操作数的数据类型是否相同
  2. 若不同,直接返回false
  3. 若相同,则比较二者是否相等

我们可以用以下表格分析。

类型(x)类型(y)结果
x和y的值相同(但不是NaN)true
字符串x和y是相同字符true
布尔值x和y都是true或falsetrue
对象x和y引用同一个对象true

让我们用代码来验证一下:

1
2
3
4
5
6
7
console.log('张三' === true); // false (两者类型不相同)
console.log('张三' === '张三') // true

var person1 = { name : '张三' };
var person2 = { name : '张三' };

console.log(person1 === person2) // false (两者引用的是不同对象)