zoukankan      html  css  js  c++  java
  • 关于 parseInt 的一道有意思的面试题

    看完标题,入坑过的同学脑海里很快会浮现出这道经典面试题,没碰到过的同学不妨跟着楼主先来复习一遍 parseInt 的用法(主要参考 MDN)。

    parseInt 是 JavaScript 中的一个全局函数(顶级函数),它会将给定的字符串以指定基数(radix/base)解析成为整数。

    它的语法非常简单:

    parseInt(string, radix)
    

    第一个参数 string 是要被解析的值,如果参数不是一个字符串,则将其转换为字符串,字符串开头的空白符将会被忽略。而第二个参数 radix 是一个 2 到 36 之间的整数值,用于指定转换中采用的基数,如果不传入,默认是 10,即按照十进制转换,这里要注意一点,如果第二个参数传入 0,和传入 10 以及不传入第二个参数等效。函数返回一个整数值,如果解析过程中发生错误,将返回 NaN。

    返回 NaN 的主要有以下几种情况:

    • 被解析参数的第一个字符无法被转化成数值类型
    • 被解析参数数值太大,不是 radix 进制下的合法数字
    • radix 不在 [2, 36] 范围内(注意其实 0 也是可以的)
    console.log(parseInt('hello', 2)); // NaN
    console.log(parseInt('3', 2)); // NaN, 3 不是合法的二进制数字
    console.log(parseInt('3', 100)); // NaN
    

    其实实际开发中我很少用 parseInt,而是用 +~~ 代替,因为它实在是太长了,但是很显然 parseInt 的使用范围更广。

    简单回顾了 parseInt 的用法,我们来看这道题:

    let ans = ["1", "2", "3"].map(parseInt);
    console.log(ans);
    

    和大多数人一样,我的第一反应也是返回 [1, 2, 3],这个时候我们有必要回顾下 Array.prototype.map,该方法的参数是一个函数,而该函数又可以接受三个参数,分别表示数组元素的值,数组元素的在数组中的索引,以及对于数组的引用。一般来说我们直接在 map 方法中传入匿名函数,但是如果这个函数是在外面定义的,传入的是方法名呢?

    let fn = (...a) => {
      console.log(a);
    };
    
    let ans = ["1", "2", "3"].map(fn);
    
    // [ '1', 0, [ '1', '2', '3' ] ]
    // [ '2', 1, [ '1', '2', '3' ] ]
    // [ '3', 2, [ '1', '2', '3' ] ]
    

    我们可以看到,如果没为该函数指定参数,那么这三个参数都会被传入!

    我们再回到这道题,parseInt 方法是可以传入 1-2 个参数的,所以 map 传入的三个参数,其实是都会被传给 parseInt 方法的,只是 parseInt 会使用前两个参数而已

    console.log(parseInt('12', 10, 'ignore')); // 12
    

    所以整个过程差不多是这样的:

    let fn = (item, index, array) => {
      return parseInt(item, index, array);
    };
    
    let ans = ["1", "2", "3"].map(fn);
    console.log(ans); // [ 1, NaN, NaN ]
    

    其实就是计算如下:

    console.log(parseInt("1", 0)); // 1
    console.log(parseInt("2", 1)); // NaN
    console.log(parseInt("3", 2)); // NaN
    

    看懂了吧不妨再试试下面这道:

    let ans = "1 2 3".replace(/d/g, parseInt);
    console.log(ans);
    

    原理是一样的,当 replace 的第二个参数是函数的时候,该函数的第一个参数是匹配模式的字符串,接下来的参数是与模式中的子表达式匹配的字符串,可以有 0 个或者多个这样的参数。接下来的参数是一个整数,声明了匹配在 StringObject 中出现的位置,最后一个参数是 StringObject 本身。

    还是一样,打印出来看看呗:

    let fn = (...a) => {
      console.log(a);
    };
    
    let ans = "1 2 3".replace(/d/g, fn);
    
    // [ '1', 0, '1 2 3' ]
    // [ '2', 2, '1 2 3' ]
    // [ '3', 4, '1 2 3' ]
    

    接下去就简单了,就是计算下面的表达式了:

    console.log(parseInt("1", 0, '1 2 3')); // 1
    console.log(parseInt("2", 2, '1 2 3')); // NaN
    console.log(parseInt("3", 4, '1 2 3')); // 3
    

    最后再加一道题:

    console.log(parseInt(Infinity, 19))
    

    前面说了,第一个参数 string 是要被解析的值,如果参数不是一个字符串,则将其转换为字符串,所以 Infinity 被转换成 "Infinity",而 19 进制数中,最大的字符就是 i,代表 18,所以解析的时候遇到 n 就停了,所以输出 18

  • 相关阅读:
    Python入门-函数进阶
    Python入门-初始函数
    Leetcode300. Longest Increasing Subsequence最长上升子序列
    Leetcode139. Word Break单词拆分
    Leetcode279. Perfect Squares完全平方数
    Leetcode319. Bulb Switcher灯泡开关
    Leetcode322. Coin Change零钱兑换
    二叉树三种遍历两种方法(递归和迭代)
    Leetcode145. Binary Tree Postorder Traversal二叉树的后序遍历
    Leetcode515. Find Largest Value in Each Tree Row在每个树行中找最大值
  • 原文地址:https://www.cnblogs.com/lessfish/p/6489703.html
Copyright © 2011-2022 走看看