美文网首页
把其他数据类型转型为Number

把其他数据类型转型为Number

作者: 小生菜呢 | 来源:发表于2021-07-22 14:47 被阅读0次

    js中的数据类型:

    1.原始值类型:
    • number
    • string
    • boolean
    • symbol
    • undefiend
    • null
    • bigint
    2.对象类型:
    • 标准普通对象
    • 标准特殊对象
    • 非标准特殊对象
    • 可调用对象(函数对象)

    【JS中的数据类型和检测:】https://www.jianshu.com/p/1c83b872154f

    其他类型转为Number:

    一般来说有两大方案:

    一、Number([val])

    • 一般情况下我们不会手动来用Numer来转(但是写了也没问题)

    这种方式一般都是通过隐式转换来完成的

    什么是隐式转换?就是浏览器自己通过Nunber()来转换

    什么情况下会存在隐式转换呢?常用的有以下三种:
    @1. 数学运算

    10-'5' = 5  // => Number('5')
    10 + '5' = '15' // 字符串拼接
    

    @2. isNaN检测

    isNaN(true)  // false           => isNaN(Number(true))
    isNaN('12px' ) // true          => isNaN(Number('12px')) (Number([val]) val有过有一个无效字符,结果就是NaN)
    

    @3. ==比较
    两边类型不一样,要默认转换成一样的类型进行比较
    .......

    • 其他类型转换为Number的一些规则:
      @1. 字符串转为数字:空字符串变为0,如果出现任何非有效数字都是NaN
      image.png
      @2. 把布尔烈性转为数字:true -> 1,false -> 0
      @3. null -> 0 undefined -> NaN
      image.png
      @4. Symbol无法转换为数字,会报错:
    image.png
    @5.bigInt去除'n'(超过安全数字的,会按照科学计数法处理)
    image.png
    所以一般情况下bigInt还是转为字符串比较合适

    @6.把对象转换为数字:

    • 先调用对象的Symbol.toPromitive 这个方法,如果不存在这个方法
    • 再调用对象的 valueof 获取原始值,如果获取的值不是原始值
    • 再调用对象的 toString 把其变为字符串
    • 最后再把字符串基于 Number方法转换为数字

    举个例子:

    let obj = {
      name: 'zhangsan'
    }
    console.log(Number(obj)) // -> NaN
    

    执行步骤:
    obj[Symbol.toPromitive] :没有Symbol.toPromitive,执行valueOf()
    obj.ValueOf() :执行valueOf()得到的不是原始值,是对象:{name: "zhangsan"},再去执行toString()
    obj.toString() -> "[object Object]"
    Number("[object Object]") -> NaN

    image.png
    let arr1 = [10],
         arr2=[10,20]
    console.log(Number(arr1 )) //  -> 10
    console.log(Number(arr2 )) // -> NaN
    
    image.png
    image.png

    普通标准对象{}和标准特殊对象[]都没有toPrimitive属性,下面来看一个有toPrimitive属性的

    let time = new Date()
    console.log(Number(time))
    
    image.png
    • 经验证time[Symbol.toPrimitive]的值是个函数,说明日期对象有这属性
    • 接下来把这个属性执行 ,直接执行会报错,如下图
    image.png
    • 所以这个属性执行的时候要传值(hint),传递的值有3种:'number','string','default',传的值不同,结果也不同
      image.png

    浏览器会帮我们判断,如果是转成数字,会传'number',如果是转成字符串,会传'string',如果浏览器也不确定,传'default'


    image.png

    上图中,浏览器帮我们处理1时,实际过程就是2,处理3时,实际过程就是4

    接下来再通过一个例子来验证下这个规则:
    给obj写个[Symbol.toPromitive]属性,执行代码看下结果

    let obj = {
      name:'张三',
      [Symbol.toPrimitive](hint) {
        console.log(hint)
        return 10
      }
    }
    console.log(Number(obj)) // 'number'  Number(10)  -> 10
    console.log(String(obj)) //'string'  String('10') -> '10' 
    console.log(obj.toString()) // '[object Object]'
    

    确认验证结果:
    1.如果有[Symbol.toPrimitive]这个属性,是溪岸执行这个属性
    2.执行[Symbol.toPrimitive]时,浏览器会默自己判断hint传的值是什么值
    3.注意:直接调用obj的toString()时,走的是Object.prototype.toString().call(obj)这套逻辑,这不是把它转换为字符串,所以不走Symbol.toPromitive
    4.对象不管是转数字还是转字符串,都是按:[Symbol.toPromitive],valueOf(),toString(),数字的话再加个Number()这顺序来转换的

    再来看个例子

    let arr = [10]
    arr[Symbol.toPrimitive] = function(hint) {
      console.log(hint)
      return 0
    }
    console.log(arr.toString()) //'10'    直接调用原型的方法,不会走 Symbol.toPrimitive这个逻辑
    console.log(arr + '') // 'default'  '0'
    
    • 第一个console.log()中,arr也是直接调的toString(),同上个例子一样,也只直接调的类的原向上的方法,所以结果是'10'
    • 第二个console得到的结果是‘default’ 和字符串'0',是因为:数组+字符串,需要把arr隐士转换为字符串[需要走Symbol.toPromitive这套逻辑,hint为‘default’],然后再进行字符串拼接
      为什么hint是'default'不是'string'呢?因为+号既是数学运算,也是字符串拼接,浏览器此时不确定是哪种情况,所以hint是default,

    所以,把一开始的规则补充冲总结下就是:
    当我们把对象隐士转换为数字或者字符串的时候[使用的方法:Nymber()/String()],会有一套自己的处理逻辑:
    @1、检测Symbol.toPrimitive,如果有这个方法,浏览器会把方法执行,传递hint[根据场景不一样,浏览器默认传递的值也不同:'number','string','default' ];如果没有这个方法,则进行下一步;
    @2、基于valueOf获取原始值,如果获取的不是原始值,再进行下一步;
    @3、基于toString获取字符串
    @4、如果需要转的是数字,则再次把字符串转为数字即可
    注意:如果是直接对象.toString(),详单与直接调用第三个步骤[直接调用所属类原型上的toString方法],此时直接获取字符串,不会走这四步的逻辑

    二、parseInt([val],[radix])和parseFloat([val])

    • 这种情况就不是隐式转换了,也就是我们说的手动转换,这两个的处理规则就和Number完全不一样了
    • 规则:[val]必须是一个字符串,如果不是则先转为字符串:然后从第一个字符开始查找,把找到的有效数字转为数字,一个都没找到就是NaN;遇到一个非有效字符,不论后边是否是有效数字,都不用再查找了;parseFloat比parseInt多识别一个小数点

    测试题

    console.log(parseInt('10'))
    console.log(Number('10'))
    
    console.log(parseInt('10px'))
    console.log(Number('10px'))
    
    console.log(parseInt(null))
    console.log(Number(null))
    
    • 第一组:10 10
    • 第二组:10 NaN
      console.log(parseInt('10px'))遇到p停止查找,所以是10
      console.log(Number('10px'))有一个非有效字符就是NaN
    • 第三组 NaN 0
      console.log(parseInt(null)):先把null转为字符串,结果是空字符串"",parseInt从左都右,一个有效字符否没找到,所以是NaN

    .

    相关文章

      网友评论

          本文标题:把其他数据类型转型为Number

          本文链接:https://www.haomeiwen.com/subject/qxismltx.html