在JavaScript中,相等有两种比较方式:普通相等比较(==,在ECMAScript标准中称为“抽象相等比较”)和 严格相等比较(===)。
对于被广泛使用的普通相等比较运算符来讲,不同类型的操作数在进行比较之前,会尝试将两个操作数转换成相同的类型,再作比较运算。而对于严格相等比较运算符来讲,仅当两个操作数的类型相同且值相等时,返回为true。
抽象相等比较
ECMAScript标准的算法细节如下:
The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:
- If Type(x) is the same as Type(y), then
- Return the result of performing Strict Equality Comparison x === y.
- If x is null and y is undefined, return true.
- If x is undefined and y is null, return true.
- If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
- If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
- If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
- If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
- If Type(x) is either String, Number, or Symbol and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).
- If Type(x) is Object and Type(y) is either String, Number, or Symbol, return the result of the comparison ToPrimitive(x) == y.
- Return false.
翻译如下:
1.如果Type(x)与Type(y)相同,执行严格相等运算x === y;
2.如果x是null,y是undefined,返回true;
3.如果x是undefined,y是null,返回true;
console.log(null == undefined); // => true
4.如果Type(x)是数值,Type(y)是字符串,返回x == ToNumber(y)的结果;
5.如果Type(x)是字符串,Type(y)是数值,返回ToNumber(x) == y的结果;
如果字符串与数值比较,先字符串将转换成数值,再进行严格相等运算
console.log(1 == '1'); // => true
6.如果Type(x)是布尔值,返回ToNumber(x) == y的结果;
7.如果Type(y)是布尔值,返回x == ToNumber(y)的结果;
- 如果操作数为布尔类型,先将布尔值转换成数值。若布尔值为true,将转换成1,若为false,将转换成0;
- 如果布尔值与字符串比较,布尔值会先转换成数值,而后便成了数值与字符串的比较;
console.log(true == 1); // => true
console.log(false == 0); // => true
console.log(true == '1'); // => true
8.如果Type(x)是字符串、数值或Symbol值,Type(y)是对象,返回x == ToPrimitive(y)的结果;
9.如果Type(x)是对象,Type(y)是字符串、数值或Symbol值,返回ToPrimitive(x) == y的结果;
如果对象与字符串、数值或Symbol值比较,先将对象转换成为一个非对象类型(non-Object type)的值。运算程序通过调用toString和valueOf方法将对象转换为其原始值(一个非对象类型的值,比如字符串或数值等)。
class Human {
toString(){
return 1;
}
}
class Animal {
valueOf(){
return 1;
}
}
let human = new Human(),
animal = new Animal();
console.log(human == 1); // => true
console.log(animal == 1); // => true
10.返回false。
以上都不匹配,则返回false
严格相等比较
ECMAScript标准的算法细节如下:
The comparison x === y, where x and y are values, produces true or false. Such a comparison is performed as follows:
- If Type(x) is different from Type(y), return false.
- If Type(x) is Number, then
- If x is NaN, return false.
- If y is NaN, return false.
- If x is the same Number value as y, return true.
- If x is +0 and y is -0, return true.
- If x is -0 and y is +0, return true.
- Return false.
- Return SameValueNonNumber(x, y).
翻译如下:
1.如果Type(x)与Type(y)不同,返回false;
2.如果Type(x)是数值,则
1.如果x是NaN,返回false;
2.如果y是NaN,返回false;
NaN,是Not a Number的缩写,在IEEE浮点数算术标准(IEEE 754)中定义,表示一些特殊数值。在ECMAScript标准中,NaN属于Number类型
console.log(typeof NaN); // => "number"
console.log(NaN === NaN); // => false
3.如果x与y数值相同,返回true;
4.如果x是+0、y是-0,返回true;
5.如果x是-0、y是+0,返回true;
console.log(+0 === -0); // => true
6.返回false。
3.返回SameValueNonNumber(x, y)的结果。
当两个操作数不是数值类型时,调用内部运算SameValueNonNumber进行比较
SameValueNonNumber(x, y)
ECMAScript标准的算法细节如下:
The internal comparison abstract operation SameValueNonNumber(x, y), where neither x nor y are Number values, produces true or false. Such a comparison is performed as follows:
- Assert: Type(x) is not Number.
- Assert: Type(x) is the same as Type(y).
- If Type(x) is Undefined, return true.
- If Type(x) is Null, return true.
- If Type(x) is String, then
- If x and y are exactly the same sequence of code units (same length and same code units at corresponding indices), return true; otherwise, return false.
- If Type(x) is Boolean, then
- If x and y are both true or both false, return true; otherwise, return false.
- If Type(x) is Symbol, then
- If x and y are both the same Symbol value, return true; otherwise, return false.
- If x and y are the same Object value, return true. Otherwise, return false.
翻译如下:
- 断言: Type(x)不是数值;
- 断言: Type(x)与Type(y)相同;
- 如果Type(x)是Undefined,返回true;
- 如果Type(x)是Null,返回true;
- 如果Type(x)是字符串,则
- 如果x与y拥有相同字符顺序,返回true;否则,返回false。
- 如果Type(x)是布尔值,则
- 如果x与y都为true或都为false,返回true;否则,返回false。
- 如果Type(x)是Symbol值,则
- 如果x与y都为同一个Symbol值,返回true;否则,返回false。
- 如果x与y是同一个Object值,返回true;否则,返回false。
伪代码
- Type(x):获取传入参数的类型
- ToNumber(x):将传入参数转换为数值
- ToPrimitive(x):获取传入参数的原始值
- SameValueNonNumber(x, y):两个同类型、非数值的传入参数的比较运算
参考
[1] ECMA. ECMAScript 标准
[2] Mozilla. MDN Web 文档
[3] 阮一峰. ECMAScript 6 入门