前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript中的比较运算符

JavaScript中的比较运算符

作者头像
贾顺名
发布2018-04-12 14:25:37
1.1K0
发布2018-04-12 14:25:37
举报

JavaScript中的比较运算符

JavaScript中的比较运算符粗略的可以分为两种:

  1. 相等运算符(==、===、!==)这些
  2. 关系运算符(>、<、>=) 在平时开发中,基本不会太关注这两者的差异,我们几乎总是可以获取到我们想要的结果-。-

前几天在群里一个小伙伴问了个问题:

console.log(null > 0) // => false
console.log(null < 0) // => false
console.log(null == 0) // => false

console.log(null >= 0) // => ?

最后一个null >= 0的结果为true。 刚看到这个代码的时候,下意识地会认为结果应该也是false,毕竟上边标明了三种情况都为false。 然而这个就露出了相等运算符关系运算符两者执行的差异。

在相等运算符中,如果是非严格相等,则会尝试将两边的值转换为相同类型进行比较。 在关系运算符中,会尝试将运算符两边的值转换为Number再进行比较。

所以在执行null >= 0的时候null被转换为Number随后值就变为了0,所以第四个运算符实际的执行为0 >= 0

觉得这个题挺有意思的,所以就去翻了下文档,看看这几个比较运算符在执行的时候都做了些什么。

相等运算符

相等运算符有四个,==!====!==,前两个会对运算符两边的表达式进行类型转换,试图转换为相同的类型。

==!=

执行时会先检查两者类型是否一致,如一致则相当于调用===!== 随后判断两者是否都为nullundefined,如果均为这两个值,则会直接返回true

接下来就会进行一些类型转换,绝大多数情况是会转换为Number,但是主要转换类型的依赖还是在于运算符左侧表达式的类型。

如果一边类型为String另一边类型为Number,则会将String转换为Number对两者进行比较。 如果其中一个为Boolean,则会将该表达式转换为Number

上边的是一些比较常规的类型转换,但是如果都不满足上边的条件,后续还会有其他的转换。 如果其中一个为Object,另一个类型为NumberString或者是Symbol中的任意一个。 则会获取Object的原始值,然后对两者进行比较。

ToPrimitive转换表格
ToPrimitive转换表格

然后表格中对Object类型又有一些额外的处理

Object类型的额外处理
Object类型的额外处理
针对==运算的Object类型的额外处理
针对==运算的Object类型的额外处理

在最后我们可以看到,会针对Object类型的变量进行调用valueOftoString 而两个函数调用的顺序取决于上边一些判断的过程,目前还木有找到会先执行toString的例子。。。(因为原始类型无法直接添加toStringvalueOf事件的代理)

我们可以用Object.assign来实现某个对象的toStringvalueOf方法来观察执行的过程。

valueOf的实现
valueOf的实现

如果valueOf返回值还是Object的话,则会继续调用toString

toString的实现
toString的实现

如果两个函数都返回Object,这时就会抛出一个类型异常的错误

Throw-TypeError
Throw-TypeError

===!==

相较=====的逻辑就很清晰了,因为没有了不同类型之间的转换,就是拿到两个表达式进行比较即可。

首先就是获取两侧表达式的类型,如果不同则返回false,相同则进行后续的比较。

关于Number类型步骤的描述,有一点我很是疑惑,就是关于+0 === -0,因为一元正负运算符的优先级肯定是高于===的,不知为何会写在这里-.-

Throw-TypeError
Throw-TypeError

关系运算符

关系运算符的执行过程,是尽可能的将两边的表达式转换为Number进行比较。(也确实,其他类型木有什么可比性的)

运算符刚开始会尝试将两侧表达式转换为原始值,并且在转换的过程中会优先选择转换为Number类型。

转换完成后,如果两边表达式都为String,则会先判断一侧表达式是否包含另一侧。 例如:

'abc' > 'ab' // abc 包含 ab 所以 abc 比 ab 大,结果为true

如果两者不为包含关系,则会从第一个字符开始获取对应的Unicode编码,来进行比大小,如果大小相同,则顺移至下一位。

check-Unicode
check-Unicode

其余情况下,则会将两侧表达式直接转换为Number求值。

Number(true)
Number({})
Number(undefined)
Number(null)
// ...

当任意一个结果为NaN时,运算符的结果都为false(而且文档中给出的,返回值为undefined,并不是false。。。)

然后针对<><=>=进行各自的判断。

所以到最后就解释了,为什么那个问题的null >= 0true。 因为关系运算符是会将值转换为Number来进行比较的。 而相等运算符只在极少数的情况下会将值转换为Number来进行比较(例如:一个为Number另一个为String

参考文档

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JavaScript中的比较运算符
  • 相等运算符
    • ==与!=
      • ===与!==
      • 关系运算符
      • 参考文档
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档