JavaScript 有两种比较方式:严格比较运算符和转换类型比较运算符。
在相等运算符中对应 ===
、!==
和 ==
、!=
。
先举个栗子
1 | var str = '1' |
相等操作符(==
)会为两个不同类型的操作数进行类型转换,然后进行严格比较。
严格相等操作符(===
),一般也叫做全等操作符。会先判断类型,再比较值是否相等。
类型转换
类型转换的途径:
类型(x) | 类型(y) | 结果
:—: | :—: | :—:
undefined | null | true
字符串 | 数字 | toNumber(x) == y
布尔值 | 数字 | toNumber(x) == y
对象 | 字符串/数字 | toPrimary(x) == y
对于两个类型不同的操作数比较。
- 字符串、布尔值都会先转换成数字类型,再做比较。
toNumber(x)
- 对于复杂数据类型,会先将其转换为原始值,之后,再根据上一个规则比较。
x = toPrimary(obj) ==> toNumber(x)
而,如何转成原始类型值呢,一般都会自动通过自带的valueOf()
方法或者toString()
方法实现。如果转换之后非原始值,比较操作会报类型错误。
1 | 具体过程: |
举个例子说明下,参考于知乎:
原始数据类型(string,number,boolean,null, undefined,symbol)。
复杂数据类型(Object, Function, Array, Date, …)
基础数据类型的比较,是值的比较,Object对象的比较,则是引用的比较
相等操作符(==
),经过类型转换之后,才比较他们的值或者对象值。
对于全等操作符(===
),等号两边的值和类型,必须完全相等。
为什么建议使用 ===
1. review代码时候,增加理解时间
在使用了 ==
的表达式中,我们需要先理解作者的意图。
- 想当然的以为都可以。
- 确实需要通过类型转换来判断。
- 不应该类型转换,但是写错了。
2. 会判断错误
1 | let num = 2 |
输出true
,
我们本意是这两者!=
,而这里得到的结果是==
,这不是我们想要的结果。
3. 会产生异常
1 | let num = 2 |
第一行输出:false
第二行输出错误提示:Uncaught TypeError: Cannot convert object to primitive value
通过前面类型转换,可以得知,一般情况下,对象会先转换为原始值。
而其过程是通过自带的valueOf()/toString()
先转换为primitive value,再和其他值做比较。
而在这里,我们手动将obj对象的valueOf()/toString()
覆盖了,导致无法实现转换为原始值。
一般情况下,建议使用===
,除非你了解,确实需要类型转换,才使用 ==
条件表达式语句(if、三目运算等)
1 | if (condition) { |
以上是if语句的基础用法。通过判断condition
的布尔值,来决定执行statement1
代码块1,还是执行statement2
代码块2。
先看下面的例子:1
2
3
4
5
6
7
8
9var s = 'str'
var blT = true
var blF = false
if (s) {
console.log('正确')
} else {
console.log('错误')
}
console.log(s == blT)
以上语句,得到的结果是1
2正确
false
为什么if语句,会执行第一个代码块。而s == blT
却是false呢?
其实,这个就涉及到类型转换的问题了。
输出“正确”
:
- if语句的条件表达式,会自动调用
Boolean()
转换函数,将这个表达式的结果转换为一个布尔值。 - Boolean(‘str’) = true
输出false
:
- 根据在上面类型转换那部分所讲,会先调用
Number()
转换函数转换为数值,之后再比较。 - Number(‘str’) = NaN
- Number(true) = 1
图表举例列出常见对象相等情况
【完】