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,否则禁用==。