深入了解parseInt

3,081 阅读4分钟

一:题目

  • 今天讲讲parseInt,之前曾看到过这么一道题:
    ['1', '2', '3'].map(parseInt)
  • 输出什么? 有些人得出的答案可能是:[1, 2, 3],这其实是一个 错误 答案。
  • 我们看看正确答案是什么,在控制台打印输出下:
    他输出的居然是:[1, NaN, NaN],有些人就很好奇它为什么输出的是[1, NaN, NaN]而不是[1, 2, 3]

二: 重新审题

    ['1', '2', '3'].map(parseInt)
  1. map(parseInt)可能会有很多疑问,这是什么写法?这其实是简写,让我们看看其他例子
    • 所以此处简写['1', '2', '3'].map(parseInt)
    • 完整写法如下['1', '2', '3'].map((v, i, arr) => parseInt(v, i))
  2. map():里面是个回调函数,三个参数:分别是当前值(v),下标(i),原始数组(arr)
  3. 执行顺序:['1', '2', '3'].map((v, i, arr) => parseInt(v, i)),依次输出:
    • parseInt('1', 0) // 1
    • parseInt('2', 1) // NaN
    • parseInt('3', 2) // NaN

三:parseInt

在这有人可能或好奇为什么第一个输出的是1,第二个和第三个是NaN,这我们就正式进入今天的主题

  1. 什么是parseInt?

    MDN: parseInt(string, radix) 将一个字符串 string 转换为 radix 进制的整数, radix 为介于2-36之间的数。最后都是以十进制形式返回。

    地址:developer.mozilla.org/zh-CN/docs/…

    所以parseInt的第二个参数是进制,但它也说明了进制时介于2~36之间的数

  2. 排除疑惑

    • 所以根据parseInt的第二个参数进制范围,我们就能知道parseInt('2', 1)为什么等于NaN
    • 那为什么parseInt('1', 0)等于1呢? 来自MDN关于parseInt的截图
      ,所以0会被当做10进制来算,所以parseInt('1', 0)等于1
    • 那为什么parseInt('3', 2)等于NaN呢? 在回答这个问题之前我们先了解下进制,来自百度百科截图

    所以parseInt的第一个参数string要小于第二个参数radix,所以parseInt('3', 2)等于NaN;

    • 根据上面的推断,我们再往里面多加一些,具体来看看:

      数组'3',...'9'之间对应的下标值就是2~8,第一个参数都大于进制,所以都是NaN

    • 那为什么第一个参数为'10',进制为9时,parseInt('10', 9)输出的不是NaN,而是9

      • 根据前面对进制的描述,9进制表示的实数就是0~8之间。第一个参数不管传入的是string还是number,他都会被挨个解析成字符串处理,所以在9进制中'1''0'属于0~8的实数
  3. 运算

    1. 在不通过控制台怎么去自己算?

      在回答这个问题之前先看下来自MDN的截图:

      注意:此处千万不要把1*5^2 + 2*5^1 + 3*5^0直接复制下来在控制台运算,不然计算出来的跟实际parseInt('123', 5)算出来的结果不一样,至于为什么,因为^是位运算符,其实在这表达的意思是几次方的意思,正确写法:1*Math.pow(5, 2) + 2*Math.pow(5, 1) + 3*Math.pow(5, 0)

      • 我们看看是怎么计算的

        他会把'123'挨个解析字符串'1','2','3',然后分别乘以Math.pow(x, y);

          x: 是底数,在这的底数就是`parseInt`的第二个参数进制`radix`
          y: 是幂数,在这的幂数就是`parseInt`的第一个参数字符串 "从右往左" 的下标值
        
      • 我们再多试几个

        • parseInt('4123', 5); // 538
        • 4*Math.pow(5, 3) + 1*Math.pow(5, 2) + 2*Math.pow(5, 1) + 3*Math.pow(5, 0) // 538

        • parseInt('764', 8); // 500
        • 7*Math.pow(8, 2) + 6*Math.pow(8, 1) + 4*Math.pow(8, 0); // 500
  4. 扩展

    1. parseInt的第一个参数string的的实数必须小于进制数?

      我们看看截图:

      • 如图:
        • 前两个解析正常,为什么第三个parseInt('125', 5)输出为7,这就不符合上面的计算公式,后来发现它自动把最后的5给删除了,输出的其实是parseInt('12', 5),这样输出就是等于7
        • 为什么第四个输出是NaN,因为参数string5开头,不符合进制所属数,所以直接返回NaN
        • 最后一个直接把55删除了,最终解析成parseInt('1', 5),输出1
    2. 结论:

      • 如果第一个参数string的第一个值就大于等于第二个参数radix,那么直接返回NaN
      • 如果第一个参数string的第一个值符合条件,其他值不符合条件,那么不符合条件的值到最后会被忽略,然后进行计算

四:课外题

1. ['10', '10', '10', '10'].map(parseInt); //输出什么
2. 1*5^2 + 2*5^1 + 3*5^0 // 输出什么,你知道它是如何运算的?

第一次写博客,如有瑕疵,还请各位大佬多多海涵