宽松相等(`==`)和严格相等(`===`)

123 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情

大家好!我是前端爬楼工程师🚹,一个野生程序员。好奇新技术,仰慕牛大佬。如果喜欢我的文章,可以关注➕点赞,为我注入能量,与我一同成长吧~


  • ==允许在相等比较中进行强制类型转换,而===不允许;
  • 两者在性能上没有什么区别,需要强制类型转换的就用==,否则===;

!! 错误的解释:===类型和值都相等,==值相等

==:抽象相等比较方法

// 特殊情况
NaN != NaN // true
+0 == -0 // true

类型相同

  • 如果两个值的类型相等,就仅比较它们是否相等; 42 == 42
  • 如果两个对象指向同一个值也视为相等,不发生强制类型转换;
var o = {name:1}
var a = o, b = o;
a==b // true

类型不同

字符串和数字之间的比较

42 == "42" // true

如果其中数字和字符串相比较,则将字符串进行ToNumber操作。

其他类型和布尔类型之间的比较

true == "42" // false

如果布尔类型比较,则对布尔类型进行ToNumber操作。 则变成了1 == "42"的比较,接着按照字符串和数字的规则,转换成 1 == 42,结果为false

那么false == "42"也是同样的道理,结果为false

"42"是一个真值,按道理来讲应该和 true 相等,因为这里不会发生ToBoolean的操作。

// bad code 
var a == "42"
if(a == true){...}
if(a === true){...}
// good code 
if(a){...}
if(!!a){...}
if(Boolean(a)){...}

nullundefined

null == undefined // true
undefined / null == 0  //false
undefined / null == false // false 其它类型和布尔类型进行比较的规则
// bad code
if(a == null || a == undefined){...}
// good code
if(a == null) 

因为我们知道nullundefined相等,这里只需要比较null或者undefined其中一个就行了

对象与非对象之间的比较

  • 如果Type(x)是字符串或数字,Type(y)是对象,比较x == ToPrimitive(y)的结果。(ToPrimitive操作和ToNumber相同)
  • 如果Type(x)是对象,Type(y)是字符串或数字,比较ToPrimitive(x)== y的结果。
[42] == "42" // true

[42]valueOf()得到的不是基本类型,走toString()转换为"42",遵循字符串和数字规则,将字符串"42"进行ToNumber,比较42==42的,结果为true

Object("abc") == "abc" // true
String("abc") == "abc" // true

Object("abc")String("abc")通过ToPrimitive拆封,返回"abc",结果为true

// undefined null NaN
Object(undefined) == undefined // false
Object(null) == null // false
Object(NaN) == NaN // false

Object(null)Object(undefined)返回一个{}。和undefinednull比较都为false Object(NaN) 是一个Number类型,解封之后是NaN,NaNNaN比较不相等

少见情况
Number.prototype.valueOf = function () {return 3}
new Number(2) === 3 // true
[] = ![] // true

ToBoolean规则转换[] == false , 布尔类型规则[] == 0 对象规则 "" == 0 ,字符串与数字比较规则 0 == 0 结果为true

有了以上规则不难看出:

[null] = "" // 结果:true 解释: [null] toString() 为 ""
[2] = 2 // 结果:true  解释:[2]toString()为"2" == 2  => 2 == 2
0 == "\n" //结果:true  解释: 空格组合都会ToNumber转换为 0

抽象关系比较

首先ToPrimitive操作,如果结果出现非字符串,还要双方进行ToNumber操作

  • 字符串之间的比较: 按字母顺序比较
["42"] < 43 // true

首先ToPrimitive["42"]转换"42",然后按字母顺序比较。

var a = {b:42}
var b = {b:43}
a < b // false
a == b // false 解释:两个对象不叫不发生强制类型转换
a <= b // true 
// 解释:在js里 a<=b 被处理 a > b 然后将结果反转,所以结果为true