• 18. JavaScript 中如何进行隐式类型转换?


    18. JavaScript 中如何进行隐式类型转换

    ToPrimitive 方法

    这是 JavaScript 中每个值隐含的自带的方法, 用来将值(无论是基本类型值还是对象)转换为基本类型值。如果值为基本类型, 则直接返回值本身; 如果值为对象, 其看起来大概是这样:

    /**
     * @obj 需要转换的对象
     * @type 期望的结果类型
     */
    ToPrimitive(obj, type)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    type 的值

    当 type 为 number 时规则
    • 调用 objvalueOf 方法, 如果为原始值, 则返回, 否则下一步
    • 调用 objtoString 方法, 后续同上
    • 抛出 TypeError 异常
    当 type 为 string 时规则
    • 调用 objtoString 方法, 如果为原始值, 则返回, 否则下一步
    • 调用 objvalueOf 方法, 后续同上
    • 抛出 TypeError 异常
    两者的主要区别

    两者的主要区别在于调用 toStringvalueOf 的先后顺序。默认情况下:

    • 如果对象为 Date 对象, 则 type 默认为 string
    • 其他情况下, type 默认为 number
    总结

    对于 Date 以外的对象, 转换为基本类型的大概规则可以概括为一个函数:

    var objToNumber = value => Number(value.valueOf().toString())
    objToNumber([]) === 0
    objToNumber({}) === NaN
    
    • 1
    • 2
    • 3

    基本类型在不同操作符的情况下隐式转换的规则

    JavaScript 中的隐式类型转换主要发生在 +-*/ 以及 ==>< 这些运算符之间。而这些运算符只能操作基本类型值, 所以在进行这些运算前的第一步就是将两边的值用 ToPrimitive 转换成基本类型, 再进行操作。对于对象, 其会被 ToPrimitive 转换成基本类型, 所以最终还是要应用基本类型转换规则。

    + 操作符

    + 操作符的两边有至少一个 string 类型变量时, 两边的变量都会被隐式转换为字符串, 其他情况下两边的变量都会被转换为数字:

    1 + '23' // '123'
    1 + false // 1
    1 + Symbol() // Uncaught TypeError: Cannot convert a Symbol value to a number
    '1' + false // '1false'
    false + true // 1
    
    • 1
    • 2
    • 3
    • 4
    • 5

    -、 *、 \ 操作符

    NaN 也是一个数字:

    1 * '23' // 23
    1 * false // 0
    1 / 'aa' // NaN
    
    • 1
    • 2
    • 3

    对于 == 操作符

    操作符两边的值都尽量转成 number:

    3 == true // false, 3 转为number为3, true转为number为1
    '0' == false //true, '0'转为number为0, false转为number为0
    '0' == 0 // '0'转为number为0
    
    • 1
    • 2
    • 3

    对于 < 和 > 比较符

    如果两边都是字符串, 则比较字母表顺序:

    'ca' < 'bd' // false
    'a' < 'b' // true
    
    • 1
    • 2

    其他情况下, 转换为数字再比较:

    '12' < 13 // true
    false > -1 // true
    
    • 1
    • 2

    以上说的是基本类型的隐式转换, 而对象会被 ToPrimitive 转换为基本类型再进行转换:

    var a = {}
    a > 2 // false
    
    • 1
    • 2

    其对比过程如下:

    a.valueOf() // {}, 上面提到过, ToPrimitive默认type为number, 所以先valueOf, 结果还是个对象, 下一步
    a.toString() // "[object Object]", 现在是一个字符串了
    Number(a.toString()) // NaN, 根据上面 < 和 > 操作符的规则, 要转换成数字
    NaN > 2 // false, 得出比较结果
    
    • 1
    • 2
    • 3
    • 4

    又比如:

    var a = {name: 'Jack'}
    var b = {age: 18}
    a + b // "[object Object][object Object]"
    
    • 1
    • 2
    • 3

    运算过程如下:

    a.valueOf() // {}, 上面提到过, ToPrimitive默认type为number, 所以先valueOf, 结果还是个对象, 下一步
    a.toString() // "[object Object]"
    b.valueOf() // 同理
    b.toString() // "[object Object]"
    a + b // "[object Object][object Object]"
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    Swoole协程
    odoo 为可编辑列表视图字段搜索添加查询过滤条件
    2022年 证券期货业信息技术服务连续性管理指南
    2023北京理工大学考研介绍
    CPP-Templates-2nd--第 21 章 模板和继承
    【BOOST C++ 8 输入输出流】(2)过滤器
    Redis数据结构:HyperLogLog
    一个对安卓日志输出功能的优化
    写年度总结报告的注意事项
    Nmap爆破MySQL弱口令漏洞:解决报错Accounts: No valid accounts found
  • 原文地址:https://blog.csdn.net/m0_51180924/article/details/126616911