聊聊javascript中的字符串和数字

185 阅读3分钟

前言:不知道其他人怎么想的,我有时候在浏览器中执行段js代码时内心通常会留下点疑问?

比如:

    console.log(typeof 123); 
    console.log(123,typeof 123);
    console.log(typeof '123'); 
    console.log('123',typeof '123');

在编译器汇总打印:

1657787010834.png

控制台中直接打印:

image.png

image.png

Tips:在浏览器中打印的结果的差异常常感到疑惑。总结下:浏览器中的console.log(typeof 123)和编译器中console.log(typeof 123)等价而浏览器中 console.log('123')和浏览器中'123'不等价;在一定条件下,黑色的字符串蓝色的数字,要在console.log()的前提下才能成立;typeof xxx 返回的一定是个字符串:'val'

toFixed()、parseFloat()、Math.round()有哪些差异呢?

  • toFixed(n) :保留n位小数;返回的是字符串;只对数字生效,这不是数学意义上的四舍五入,它是银行家算法
    let a = 12.125
    console.log(a.toFixed(2),typeof a.toFixed(2)); // 12.13 string
  • parseFloat() :保留所有小数位;返回的是数字;对数字、字符串、数组都生效,保留整数位的同时;保留小数位(由于该方法可能在不同版本的 JavaScript 和浏览器中实现不同,因此建议传递基数就是要传第二个参数。)
    let a = 12.125
    console.log(parseFloat(a),typeof parseFloat(a,10)); // 12.125 'number'
  • Math.round() :保留一位小数位;返回的是数字;对数字、字符串、数组都生效,这是数学意义上的四舍五入
    let a = 12.125
    console.log(Math.round(a),typeof Math.round(a)); // 12 'number'

下面这段代码说明,上面总结提到的:黑色的字符串蓝色的数字是在console.log()的前提下的这种结论是错误的,在特定情况下才是这样的,并且要知道知道typeof 返回的一定是个字符串就ok!

    console.log(typeof a.toFixed(2)); // string

    console.log(typeof parseFloat(a)); // number

    console.log(typeof Math.round(a)); // number

怎么解决toFixed()四舍五入的bug?

    let a = 10.045
    let b = 10.0455
    let decimal = 2
    
    // 自定义一个方法
    function toFixed(num, small) {
      var times = Math.pow(10, small)
      var des = num * times + 0.5
      des = parseInt(des, 10) / times
      return des + ''
    }

    console.log(a.toFixed(decimal)); // 10.04 这个官方的方法是银行家算法,不算真正意义上的“四舍五入”
    console.log(b.toFixed(decimal)); // 10.05

    console.log(toFixed(a, decimal)); // 10.05 这才我们理解的四舍五入
    console.log(toFixed(b, decimal)); // 10.05

Tips:将小数点左移s(参数)个单位,加上0.5后取整完成四舍五入,如 1.236.toFixed(2) 小数点左移两个单位 -> 123.6 + 0.5 = 124.1 取整 -> 124,最后再将小数点右移s个单位后将Float类型格式化为String类型后return即可。

    let a = 1.23
    let b = 10.0455
    let decimal = 3

    function toFixed(num, small) {
      var times = Math.pow(10, small)
      var des = num * times + 0.5
      des = parseInt(des, 10) / times
      return des + ''
    }

    console.log(toFixed(a,decimal)); // 1.23  有问题,为什么没有保留small位i小数?
    console.log(toFixed(b,decimal)); // 10.046

Tips:当值为1.23时,有个bug,假设参数大于浮点数长度,1.23.toFixed(3) 运算过程 -> 1230 -> 1230.5 -> 1230 -> 1.23,此处的 + 0.5 完全是无效的,且理想结果应补零至千分位得到 1.230 ,优化该方法(可用最终版):

最终版本:

     Number.prototype.toFixed = function (s) {
      changenum = (parseInt(this * Math.pow(10, s) + 0.5) / Math.pow(10, s)).toString()
      index = changenum.indexOf(".")
      if (index < 0 && s > 0) {
        changenum = changenum + "."
        for (i = 0; i < s; i++) {
          changenum = changenum + "0"
        }
      } else {
        index = changenum.length - index;
        for (i = 0; i < (s - index) + 1; i++) {
          changenum = changenum + "0"
        }
      }
      return changenum;
    }

    console.log(a.toFixed(decimal)); // 1.230
    console.log(b.toFixed(decimal)); // 10.046