你真的理解了比较运算符吗?

2019-11-02 admin

平常我们都是不建议在代码上编写一些比较难理解的代码,例如 x == y'A' > 'B' 。这篇文章或许不能给你带来什么大的帮助,但是却可以让你了解一些你可能没接触到的知识点。

由于有些参考资料来源于 ECMA 规范,所以感兴趣的可能需要先看《读懂 ECMAScript 规格》这篇文章,当然也可以忽略。

类型之间的转换表

首先我们需要先了解基本的类型转换规则。

粗体需要特别留意的,可能跟你想象中的不一样。

原始值 转换为数字 转换为字符串 转换为布尔值
false 0 “false” false
true 1 “true” true
0 0 “0” false
1 1 “1” true
“0” 0 “0” true
“000” 0 “000” true
“1” 1 “1” true
NaN NaN “NaN” false
Infinity Infinity “Infinity” true
-Infinity -Infinity “-Infinity” true
“” 0 “” false
“20” 20 “20” true
“Runoob” NaN “Runoob” true
[ ] 0 “” true
[20] 20 “20” true
[10,20] NaN “10,20” true
[“Runoob”] NaN “Runoob” true
[“Runoob”,“Google”] NaN “Runoob,Google” true
function(){} NaN “function(){}” true
{ } NaN “[object Object]” true
null 0 “null” false
undefined NaN “undefined” false

这里根据上面的表格列举些例子:

  • 数字转字符串

    这个最常用了,这个也很好理解。

    String(123)
    

    或者

    const a = 123;
    a.toString();
    
  • 将字符串转换为数字

    Number("3.14")    // 返回 3.14
    Number(" ")       // 返回 0
    Number("")        // 返回 0
    Number("99 88")   // 返回 NaN
    
  • 字符串转布尔值

    Boolean('test')  // 返回 true
    Boolean('0')  // 返回 false
    Boolean('000')  // 返回 true
    

== 比较运算符

规则来源于 ECMA 相关规范 Abstract Equality Comparison

== 等同运算符的两边的类型不一样的时候,会有类型自动转换规则。

相同的类型可以直接比较(相当于 === 比较),无需自动转换,不同类型有下面几种自动转换规则(x == y),规则优先级自上而下:

  1. 如果 x 是 null,y 是 undefined,返回 true

    null == undefined
    
  2. 如果 x 是 undefined,y 是 null,返回 true

    undefined == null
    
  3. 如果 x 是 Number,y 是 String,将 y 转化成 Number,然后再比较

    0 == '0' // true
    0 == '1' // false
    
  4. 如果 x 是 String,y 是 Number,将 x 转化成 Number,然后再比较

    '0' == 0 // true
    '1' == 0 // false
    
  5. 如果 x 是 Boolean,那么将 x 转化成 Number,然后再比较

    true == 0 // false
    true == 1 // true
    true == 2 // false
    true == 'test' // false
    false == 0 // true
    false == 1 // false
    false == 2 // false
    false == 'test' // false
    
  6. 如果 y 是 Boolean,那么将 y 转化成 Number,然后再比较

    0 == true // false
    1 == true // true
    2 == true // false
    'test' == true // false
    0 == false // true
    1 == false // false
    2 == false // false
    'test' == false // false
    
  7. 如果 x 是 String 或者 Number,y 是 Object,那么将 y 转化成基本类型,再进行比较

    const a = {}
    1 == a    // false
    '1' == a  // false
    true == a // false
    
  8. 如果 x 是 Object,y 是 String 或者 Number,将x转化成基本类型,再进行比较

    const a = {}
    a == 1    // false
    a == '1'  // false
    a == true // false
    
  9. 其他情况均返回 false

    const a = {}
    a == null
    a == undefined
    0 == null
    '2' == null
    false  === null
    

即使我们搞懂了 == 的规则,还是建议使用 === 这种严格的运算符来替代 ==

> 或者 < 比较运算符

规则来源于 ECMA 相关规范 Abstract Relational Comparison

x < y 的规则步骤如下(规则优先级自上而下):

  1. x 和 y 需要转换为原始数据类型(ToPrimitive)

    var px = ToPrimitive(x)
    var py = ToPrimitive(y)
    // 下面会沿用这两个变量的
    

    除开原始的数据类型 undefined、null、boolean、number、string、 symbol,其他的都属于对象,所以可以理解为这个 ToPrimitive 只对对象有作用。(还有个特殊的 NaN,不需要转换,NaN 可以理解为一种特殊的 number,typeof NaN === ‘number’)。

    如果 x 或者 y 是对象,需要做转换处理,由于这里涉及的比较深,这里还是简单的说一下,知道有这回事就好。

    var a = {}
    a < 'f' // true
    a < 'F' // false
    // a 会转变为 [object Object]
    // 相当于运行了 a.valueOf().toString()
    

    为什么不直接 a.toString() 呢,看下下面的例子你就懂了(会首先运行 valueOf,如果返回的是对象则再运行 toString,否则直接返回 valueOf 的返回值)

    var d = new Date(1572594637602)
    d < 1572594637603 // true
    d < 1572594637601 // false
    // d 会转变为 1572594637602 (当前时间转变的成的毫秒时间戳)
    // 相当于运行了 a.valueOf()
    

    如果重写了 valueOf 方法,那么预期结果就不一样了

    var d = {}
    // 这里重写定义了valueOf
    d.valueOf = () => 1
    d < 2 // true
    d < 0 // false
    // d 会转变为 1
    // 相当于运行了 a.valueOf()
    
  2. 如果 px 和 py 都是字符串

    • 如果 py 是 px 的前缀,返回 false

      'test' < 'te'
      
    • 如果 px 是 py 的前缀,返回 true

      'test' < 'test1'
      
    • 如果 px 不是 py 的前缀,而且 py 也不是 px 的前缀

      那么需要从 px 和 py 的最小索引(假设是 k)对应的字符的 UTF-16 代码单元值 进行对比。

      假设 m = px.charCodeAt(k),n = py.charCodeAt(k),那么如果 m < n,返回 true,否则返回 false。

      'A' < 'B' // true
      // 相当于 'A'.charCodeAt(0) < 'B'.charCodeAt(0)
      

      更加复杂点的例子

      'ABC' < 'ABD' // true
      // 相当于 
      // var a = 'ABC'.charCodeAt(0) < 'ABD'.charCodeAt(0) // false
      // var b = 'ABC'.charCodeAt(1) < 'ABD'.charCodeAt(1) // false
      // var c = 'ABC'.charCodeAt(2) < 'ABD'.charCodeAt(2) // true
      // a || b || c
      
  3. 其他情况 px 和 py 一律转为数字类型进行比较

    var nx = Number(px)
    var ny = Number(py)
    

    例子

    '2' < 3 // true
    '2' < 1 // false
    var a = {}
    a < 1 // false,相当于,Number(a) < 1
    a < 'a' // true,相当于 '[object Object]' < 'a'
    a < '[' // false,相当于 '[object Object]' < '['
    var b = function(){}
    b < 'g' // true,相当于 'function(){}' < 'g'
    b < 'e' // false,相当于 'function(){}' < 'e'
    

x > y 的道理一样,这里就不多说了。

参考文章

[转载]原文链接:https://segmentfault.com/a/1190000020883005

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-78772.html

文章标题:你真的理解了比较运算符吗?

相关文章
10个强大的纯CSS3动画案例分享
我们的网页外观主要由CSS控制,编写CSS代码可以任意改变我们的网页布局以及网页内容的样式。CSS3的出现,更是可以让网页增添了不少动画元素,让我们的网页变得更加生动有趣,并且更易于交互。本文分享了10个非常炫酷的CSS3动画案例,希望大家...
2015-11-16
v-charts | 饿了么团队开源的基于 Vue 和 ECharts 的图表工具
在使用echarts生成图表时,经常需要做繁琐的数据类型转化、修改复杂的配置项,v-charts的出现正是为了解决这个 痛点。基于Vue2.0和echarts封装的v-charts图表组件,只需要统一提供一种对前后端都友好的数据格式 设置简...
2018-05-24
Node.js 2014这一年发生了什么
Node.js 的 2014 年充满了不幸和争议. 这一年 Noder 们经历了太多的伤心事, 经历了漫长的等待, 经历了沉重的分裂之痛. 也许 Noder 们不想回忆14年 Node.js land 发生的事情, 但正因为痛才更有铭记的价...
2015-11-12
从2014年的发展来展望JS的未来将会如何
&lt;font face=&quot;寰�杞�闆呴粦, Arial, sans-serif &quot;&gt;2014骞达紝杞�浠惰�屼笟鍙戝睍杩呴€燂紝鍚勭�嶈��瑷€灞傚嚭涓嶇┓锛屼互婊¤冻鐢ㄦ埛涓嶆柇鍙樺寲鐨勯渶姹傘€傝繖浜涜��...
2015-11-12
WebSocket断开原因分析,再也不怕为什么又断开了
阅读原文:https://wdd.js.org/websocket-… 1. 把错误打印出来 WebSocket断开的原因有很多,最好在WebSocket断开时,将错误打印出来。 在线demo地址:https://wdd.js.org/we...
2018-04-25
12个你未必知道的CSS小知识
虽然CSS并不是一种很复杂的技术,但就算你是一个使用CSS多年的高手,仍然会有很多CSS用法/属性/属性值你从来没使用过,甚至从来没听说过。 1.CSS的color属性并非只能用于文本显示 对于CSS的color属性,相信所有Web开发人员...
2015-11-12
ajax为什么令人惊异?ajax的优缺点
使用Ajax的最大优点,就是能在不更新整个页面的前提下维护数据。这使得Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变的信息。 Ajax不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。就像DHT...
2015-11-12
HTML5的5个不错的开发工具推荐
HTML5规范终于在今年正式定稿,对于从事多年HTML5开发的人员来说绝对是一个重大新闻。数字天堂董事长,DCloud CEO王安也发表了文章,从开发者和用户两个角度分析了HTML对两个人群的优势。其实,关于HTML5的开发工具,我们以往的...
2015-11-12
JS中的语音合成——Speech Synthesis API
JS中的语音合成——Speech Synthesis API 简介 HTML5中和Web Speech相关的API实际上有两类,一类是“语音识别(Speech Recognition)”,另外一个就是“语音合成(Speech Synthes...
2018-05-17
JavaScript教程:JS中的原型
Keith Peters 几年前发表的一篇博文,关于学习没有“new”的世界,其中解释了使用原型继承代替构造函数。两者都是纯粹的原型编码。 标准方法(The Standard Way) 一直以来,我们学习的在 JavaScript 里创建对...
2015-11-12
回到顶部