js中相等比较背后的原理

在js中使用==进行的比较叫做相等比较,判断语句中经常会用到==进行相等比较。如果两个值不是同一个类型,js引擎就会在背后“偷偷”做一些事情(隐式类型转换)进行处理。

简单示例

以下代码示例,可能第一感觉第一个返回true,第二个返回true,其实不然

[] == 0  // true
[0] == [0] // false

两个操作在进行相等比较时,如果两个操作数类型不一致的时候,就会根据一定的规则进行强制类型转换,转换完之后再进行比较。

转换规则

在两个操作数类型不一致时,比较转换规则如下:

  • 两个操作数中如果有布尔值,则先将布尔值转换成数值--false会转换成0,true会转换成1

  • 两个操作数分别为字符串和数值,则先将字符串转成数值

  • 一个操作数为对象,另外一个操作数不是对象,则调用valueOf方法获取原始值,然后再进行比较;如果调用valueOf方法不能获取原始值,则使用toString方法获取原始值,然后进行比较

  • null和undefined是相等的

  • null和undefined不能转化成其他值进行比较

  • 操作数其一是NaN,相等操作会返回false,即使另外一个操作数也是NaN

  • 两个操作数都是对象的时候,会比较它们是不是同一对象,同一对象返回true,不同对象返回false

根据上述的转换规则不难分析以上代码是如何比较的:

  • [] == 0

    • 调用[]数组的vlaueOf方法,但返回值是数组本身,不是基本类型的值

    • 调用[]数组的toString方法,此时会返回空字符串('')

    • 因由一操作数为数字,空字符串进行强制类型转换为数值:Number('') 返回0

    • [] == 0最终会转换成0 == 0,所以返回true

  • [0] == [0]

    • 两个操作数非同一个数组对象,根据比较规则返回false

特殊相等比较

根据比较规则,一些比较容易出错的相等比较如下:

true == 1 // true
false == 0 // true
'5' == 5 // true
NaN == 1 // false
NaN == NaN // false
null == undefined // true
null == 0 // false,不发生强制类型转换
undefined == 'undefined' // false,不发生强制类型转换
[] == 0 // true
[0] == [0] // false

“奇葩”场景

由于对象与基本类型值进行相等比较时,会先调用对象的valueOf、toString方法,只要我们改写了其中一个方法使其返回基本类型值,就可以写出来一些很“奇葩”的代码。

var value = {
  index: 0,
  toString() {
    return this.index++
  }
};

value == 0 && value == 1

在上述代码中,重写了对象的toString方法,根据对象与基本类型值的比较规则,每次比较会调用toString方法返回基本类型值,之后index会增加1,所以上述代码value == 0 && value == 1会返回true。

替代方案

由于==比较会在我们看不到的地方“偷偷”做一些事情,这就导致了代码的运行结果可能有时候并不符合我们的预期,增加了我们排查问题的难度,建议在代码使用===比较(全等比较),全等比较不会做隐式类型转化。

===比较也存在一个小小的问题,NaN在全等比较的时候也是不等于自身的,并且也无法比较+0与-0。当需要比较的值有NaN、+0、-0等的时候,可以使用ES6+新增的方法Object.is进行比较。

Object.is(NaN, NaN) // true
Object.is(+0, -0) // false
Object.is(+0, +0) // true
Object.is(-0, -0) // true

本文首发于微信公众号(Web前端技术),关注公众号及时获取最新内容~

  • 31
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值