在上班摸鱼的时候重新回看了一下经典的小黄书系列,重新学习了一下 宽松比较和严格比较
宽松相等(loose equals)==
和严格相等(strict equals)===
都用来判断两个值是否“相等”,但是它们之间有一个很重要的区别,特别是在判断条件上。
发现了有一个之前一直有被误导的地方就是, ==检查值是否相等,===检查值和类型是否相等
正确的解释应该是 ==允许在相等比较中进行强制类型转换,而===不允许
小黄书中的原话: 常见的误区是“==检查值是否相等,===检查值和类型是否相等”。听起来蛮有道理,然而还不够准确。很多JavaScript的书籍和博客也是这样来解释的,但是很遗憾他们都错了。
在类型相同的情况下
基本数据类型 直接比较值
5 == 5 // true
5 ===5 // true
hello == hello //true
hello === hello //true
true == true // true
true === true // true
复杂数据类型 比较的是引用地址
let a = {}
let b = {}
a == b // false
a === b // false
let c = b
c == b // true
c === b // true
如果比较的是两个不同的数据类型
null
与 undefined
null == undefined // true
null === undefined // true
null
和 undefined
之间的 == 也涉及隐式强制类型转换
在 == 中 null 和 undefined 相等(它们也与其自身相等),除此之外其他值都不存在这种情况
也就是说,在==中null和undefined是一回事,可以相互进行隐式强制类型转换
let a = null;
let b;
a == b; // true
a == null; // true
b == null; // true
a == false; // false
b == false; // false
a == ""; // false
b == ""; // false
a == 0; // false
b == 0; // false
数字与字符串比较
55 == '55' // true
55 === '55' // false
由于没有强制类型转换 55 === '55', 55 与 '55' 为false, 55 与 '55'不相等
而 55 == '55', 是宽松相等, 对其中之一进行了,强制类型转换
具体是如何转换的?
是数字的55转换成了字符串的'55',还是字符串的'55'转换成了数字的55呢?
es5规范中的定义
简单来说就是, 无论前者是字符串或者是数字(或者反之),都将字符串类型转换成数字类型进行比较
55 ==='55' 会转换成 55 === ToNumber('55') 来进行比较
布尔值与其他类型
true == '5' // false
false == '5' // false
在布尔值的比较中,会将布尔值 false 转换成 0 , true 转换成 1 来进行比较
true == '5' ==> 1 == '5' ==> 1 == 5
false =='5' ==> 0 == '5' ==> 0 == 5
这里有一个疑问就是 字符串的 5 是一个真值,但是为什么 不等于 true 其实他的流程是先将布尔值转换成 0 或者是 1 如果在转换后与其比较的是数字类型会直接进行比较,如果是其他类型会继续进行类型转换直至是数字类型为止,所以并不是 拿的 true 与 true 进行比较
let a = '5'
// 不要这样用,条件判断不成立:
if (a == true) { // .. }
// 也不要这样用,条件判断不成立:
if (a === true) { // .. }
// 这样的显式用法没问题:
if (a) { // .. }
// 这样的显式用法更好:
if (! ! a) { // .. }
// 这样的显式用法也很好:
if (Boolean( a )) { // .. }
所以无论什么情况下都不要使用== true和== false(布尔值的宽松相等)
对象与非对象类型
5 == [5] // true
5 === [5] // false 类型不同
这里会将对象类型转换成基本数据类型之后再进行比较
5 == [5] ==> 5 ==> '5' ==> 5 == 5
NaN
和任何值(包括它自己)比较都返回 false
,不管是 ==
还是 ===
。
NaN == NaN // false
NaN === NaN // false
Alex Dorey(GitHub用户名@dorey)在GitHub上制作了一张图表,列出了各种相等比较的情况
总结
左侧 | 右侧 | == 结果 | === 结果 | 备注 |
---|---|---|---|---|
null | undefined | true | false | 仅 == 相等 |
数字 | 字符串 | 比较时字符串转换为数字 | false | "42" == 42 为 true |
布尔值 | 数字 | 布尔值转换为 0 /1 | false | true == 1 为 true |
对象 | 原始类型 | 对象转换为原始值 | false | [1] == "1" 为 true |
数字 | NaN | false | false | NaN 不等于任何值 |
空字符串 | 数字 0 | true (空字符串为 0 ) | false | "" == 0 为 true |
空字符串 | false | true | false | "" == false 为 true |
引用类型 | 引用类型 | 引用相同则相等 | 引用相同则相等 | 比较的是引用地址 |
-
宽松相等(
==
) :会进行隐式类型转换,这使得不同类型的值可以比较,但也会导致不可预测的行为。 -
严格相等(
===
) :不会进行任何类型转换,因此类型和值都必须相同才返回true
。
为了代码的可读性和避免潜在的错误,强烈建议使用严格相等(===
) ,尤其在不需要类型转换的情况下。宽松相等虽然可以节省代码量,但也会带来不可预测的隐式类型转换问题,从而增加代码维护的复杂度和潜在错误
以上为个人学习记录,内容中可能存在理解或表达上的不足。如果您发现任何错误或有改进建议,欢迎指出,非常感谢您的帮助。