JavaScript的===和==
原文:Triple Equals vs Double Equals in JavaScript
何时使用==
,何时使用===
,经常会导致开发者困惑不已。简单的版本:除了一个小小的例外,应该一直使用===
。
在JavaScript中,技术上有4种不同的方式可以比较两个值是否相等。最常用的2种是==
运算符和===
运算符,也可以叫做宽松相等和严格相等。
=== 严格相等
2个值x
和y
,JavaScript这样检查是否x === y
:
- 检查
x
和y
的类型。如果是不同类型,返回false。 - 如果
x
和y
是数值,先检查x
或y
是不是NaN
,其中一个是NaN
则返回false。如果x
和y
是+0
或-0
,返回true
。其他情况,检查它们是否是相同数值。 - 如果
x
和y
都是null
或都是undefined
,返回true
。 - 如果
x
和y
都是Boolean
、或String
、或Symbol
,根据值进行比较。 - 如果
x
和y
都是对象,只有在它们指向相同对象时才返回true
。
简言之,===
最重要的细节是:
- 没有隐式的类型转换。
===
不会调用valueOf()
或尝试用其他方式把对象转为原始类型。 - 没有任何值
=== NaN
。不要用===
检查NaN,用Number.isNaN()。 - 对象比较是按引用比较——两个不同的对象,包含完全相同的键值对,但
===
认为它们是不相等的。
1 | const obj1 = { answer: 42 }; |
宽松相等 ==
==
运算符使用更复杂的抽象相等比较算法,来比较x
和y
是否相等。总结如下:
- 如果
x
和y
是相同类型,检查x === y
是否成立。 - 如果
x
和y
都是null或都是undefined,返回true。 - 如果
x
是数值而y
是字符串,将y
转换为数值,然后用===
比较。类似的,如果x
是布尔值或字符串,而y
是数值,则x
转换为数值。 - 如果
x
或y
是布尔值,将另一个值转换为数值进行比较。 - 如果
x
是对象,而y
是Symbol、或字符串、或数值,尝试用valueOf()函数将x
转换为原始类型,然后用===
进行比较。
宽松相等会造成很多著名的BUG场景。
1 | ' ' == 0; // true |
一般来说,应该总是用===
,而非==
,除非你有确切的理由。==
有一个简洁的用途:一次检查是否为null
或undefined
(所谓的空值):
1 | // 只有在`v === null`或`v === undefined`才是true |
v == null
是检查v
是否严格等于null
或undefined
的一种简便方法,如果你是一个熟练的JavaScript开发者,这样使用是没问题的。但是,一直使用===
也是没错的,而且更安全。
ESLint有一条规则,除非右侧是null
,否则禁用==
。