shuangmianxiaoQ / Daily-Interview-Question

工作日每天一道前端大厂面试题,每天进步一点点,一年后会看到不一样的自己。
0 stars 0 forks source link

第 2 期:['1', '2', '3'].map(parseInt) what & why ? #2

Open shuangmianxiaoQ opened 5 years ago

shuangmianxiaoQ commented 5 years ago

首先我的答案是:[1, NaN, 11],下面来解释一下:

这个函数的疑惑点关键在于 map 中的参数,并没有写回调函数,而是简化成一个 parseInt,那么究竟是怎么个执行过程呢,先来还原下这个函数:

['1', '2', '3'].map((val, i, arr) => parseInt(val, i));

上面这个写法等价于那个简化的写法,不难看出,这里的 parseInt 有两个参数,而这也正是很多人会遗忘的。因为习惯性地使用 parseInt 只写一个参数,以为它只有一个参数,实际上 parseInt 是有第二个参数的,参数的含义是转化的进制,默认为十进制。所以执行完毕后,得到的是零进制的 1,一进制的 2 和二进制的 3

那么,上面这个问题该如何解决呢,在 lodash 中,有 aryunary 这样的工具函数可以解决,它们的作用就是限制 函数调用的参数格式限制:

import { ary, unary } from 'lodash';
['1', '2', '3'].map(ary(parseInt, 1))
['1', '2', '3'].map(unary(parseInt))

aryunary 方法在 30 seconds of code 中的简单实现:

const ary = (fn, n) => (...args) => fn(args.slice(0, n));
const unary = fn => val => fn(val);
shuangmianxiaoQ commented 5 years ago

上面的思路是没问题,但是答案还是错了,这个就有点尴尬了。

主要还是 parseInt 方法的理解没到位,MDN 的使用介绍:parseInt - JavaScript | MDN,简要总结下:

parseInt(string, radix)

  1. 如果 radixundefined,或者 radix0 或者没有指定的情况下:
    • 如果字符串 string 以"0x"或者"0X"开头, 则基数是16 (16进制) // parseInt('0xff') -> 256
    • 如果字符串 string 以"0"开头, 基数是 8(八进制)或者 10(十进制),那么具体是哪个基数由实现环境决定。ECMAScript 5 规定使用 10,但是并不是所有的浏览器都遵循这个规定。因此,永远都要明确给出 radix 参数的值。 // parseInt('099') -> 99
    • 如果字符串 string 以其它任何值开头,则基数是10 (十进制)。
  2. radix 是一个介于 236 之间的整数
    • 如果 radix 不介于 236 之间,则返回 NaN // parseInt('2', 1) -> NaN
    • radix 介于 236 之间时,就是对应的进制,而且 Number(string) < radix时才能返回正确的结果,否则返回 NaN // parseInt('3', 2) -> NaN
shuangmianxiaoQ commented 5 years ago

参考答案: https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/4#issuecomment-464319423