Skip to content

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

@YuYuBei

Description

@YuYuBei

第一眼看到这个题目的时候,脑海跳出的答案是 [1, 2, 3],但是真正的答案是[1, NaN, NaN]

  • 首先让我们回顾一下,map函数的第一个参数callback:

var new_array = arr.map(function callback(currentValue[, index[, array]]) { // Return element for new_array }[, thisArg])
这个callback一共可以接收三个参数,其中第一个参数代表当前被处理的元素,而第二个参数代表该元素的索引。

  • 而parseInt则是用来解析字符串的,使字符串成为指定基数的整数。
    parseInt(string, radix)
    接收两个参数,第一个表示被处理的值(字符串),第二个表示为解析时的基数。

  • 了解这两个函数后,我们可以模拟一下运行情况

  1. parseInt('1', 0) //radix为0时,且string参数不以“0x”和“0”开头时,按照10为基数处理。这个时候返回1
  2. parseInt('2', 1) //基数为1(1进制)表示的数中,最大值小于2,所以无法解析,返回NaN
  3. parseInt('3', 2) //基数为2(2进制)表示的数中,最大值小于3,所以无法解析,返回NaN

Activity

changed the title [-]['1', '2', '3'].map(parseInt) 解析[/-] [+]第二题:['1', '2', '3'].map(parseInt) 解析[/+] on Feb 12, 2019
mengfei-nie

mengfei-nie commented on Feb 13, 2019

@mengfei-nie

parseInt 基数是一个介于2和36之间的整数 可能第二点这个说法不太准确

atheist1

atheist1 commented on Feb 14, 2019

@atheist1

在30-seconds-of-code看到一个这个题的变形,分享一下

let unary = fn => val => fn(val)
let parse = unary(parseInt)
console.log(['1.1', '2', '0.3'].map(parse))
xingorg1

xingorg1 commented on Feb 15, 2019

@xingorg1

我开始也这么理解:第二个参数需要的范围是2~36之间,如果小于 2 或者大于 36,则 parseInt() 将返回 NaN。但是parseInt(5,4),第二个参数在[2,36]之间,但是结果依旧返回NaN啊。
所以后俩返回NaN,我们是不是又两种角度可以理解呢?

sisterAn

sisterAn commented on Feb 16, 2019

@sisterAn
Collaborator

这是今天在 Advanced-Frontend组织 看到一个比较有意思的题目。
主要是讲JS的映射与解析
早在 2013年, 加里·伯恩哈德就在微博上发布了以下代码段:

['10','10','10','10','10'].map(parseInt);
// [10, NaN, 2, 3, 4]

parseInt

parseInt() 函数解析一个字符串参数,并返回一个指定基数的整数 (数学系统的基础)。

const intValue = parseInt(string[, radix]);

string 要被解析的值。如果参数不是一个字符串,则将其转换为字符串(使用 ToString 抽象操作)。字符串开头的空白符将会被忽略。

radix 一个介于2和36之间的整数(数学系统的基础),表示上述字符串的基数。默认为10。
返回值 返回一个整数或NaN

parseInt(100); // 100
parseInt(100, 10); // 100
parseInt(100, 2); // 4 -> converts 100 in base 2 to base 10

注意:
radix为 undefined,或者radix为 0 或者没有指定的情况下,JavaScript 作如下处理:

  • 如果字符串 string 以"0x"或者"0X"开头, 则基数是16 (16进制).
  • 如果字符串 string 以"0"开头, 基数是8(八进制)或者10(十进制),那么具体是哪个基数由实现环境决定。ECMAScript 5 规定使用10,但是并不是所有的浏览器都遵循这个规定。因此,永远都要明确给出radix参数的值。
  • 如果字符串 string 以其它任何值开头,则基数是10 (十进制)。

更多详见parseInt | MDN

map

map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。

var new_array = arr.map(function callback(currentValue[,index[, array]]) {
 // Return element for new_array
 }[, thisArg])

可以看到callback回调函数需要三个参数, 我们通常只使用第一个参数 (其他两个参数是可选的)。
currentValue 是callback 数组中正在处理的当前元素。
index可选, 是callback 数组中正在处理的当前元素的索引。
array可选, 是callback map 方法被调用的数组。
另外还有thisArg可选, 执行 callback 函数时使用的this 值。

const arr = [1, 2, 3];
arr.map((num) => num + 1); // [2, 3, 4]

更多详见Array.prototype.map() | MDN

回到真实的事例上

回到我们真实的事例上

['1', '2', '3'].map(parseInt)

对于每个迭代map, parseInt()传递两个参数: 字符串和基数
所以实际执行的的代码是:

['1', '2', '3'].map((item, index) => {
	return parseInt(item, index)
})

即返回的值分别为:

parseInt('1', 0) // 1
parseInt('2', 1) // NaN
parseInt('3', 2) // NaN, 3 不是二进制

所以:

['1', '2', '3'].map(parseInt)
// 1, NaN, NaN

由此,加里·伯恩哈德例子也就很好解释了,这里不再赘述

['10','10','10','10','10'].map(parseInt);
// [10, NaN, 2, 3, 4]

如何在现实世界中做到这一点

如果您实际上想要循环访问字符串数组, 该怎么办? map()然后把它换成数字?使用编号!

['10','10','10','10','10'].map(Number);
// [10, 10, 10, 10, 10]

本文始发于我的博客:['1', '2', '3'].map(parseInt) what & why ?

jialinhome

jialinhome commented on Feb 18, 2019

@jialinhome

parseInt(string, radix)
这道题的关键点在于parseInt的返回值类型,MDN中说返回值类型为10进制,具体是把string所对应的值当做radix对应的进制看待,然后转换成相应的10进制值。
所以在parseInt('3', 2) 中,'3'在2进制中是一个非法的值,2进制中只能存在0和1,所以最后返回了NAN

ravencrown

ravencrown commented on Feb 18, 2019

@ravencrown

parseInt(string, radix),radix在 (2, 8)的时候,Number(string) < radix。

lmislm

lmislm commented on Feb 18, 2019

@lmislm

我开始也这么理解:第二个参数需要的范围是2~36之间,如果小于 2 或者大于 36,则 parseInt() 将返回 NaN。但是parseInt(5,4),第二个参数在[2,36]之间,但是结果依旧返回NaN啊。
所以后俩返回NaN,我们是不是又两种角度可以理解呢?

4进制最大数是3,5大于3,所以NaN。

ravencrown

ravencrown commented on Feb 18, 2019

@ravencrown

ratio 值为 (2, 8)的时候,parseInt的第一个参数必须小于ratio

Jer-X

Jer-X commented on Feb 19, 2019

@Jer-X

我开始也这么理解:第二个参数需要的范围是2~36之间,如果小于 2 或者大于 36,则 parseInt() 将返回 NaN。但是parseInt(5,4),第二个参数在[2,36]之间,但是结果依旧返回NaN啊。
所以后俩返回NaN,我们是不是又两种角度可以理解呢?

第二个参数是处于2~36没错,但是第二个参数代表解析的进制数,在四进制里面是不可能会出现5这个数字的,所以返回的就是NaN,要想转成5的话应该是parseInt('11', 4)结果就是5

yinyangshibolange

yinyangshibolange commented on Feb 19, 2019

@yinyangshibolange
string 必需。要被解析的字符串。
radix 可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。

copyed from W3School

yishuihan-001

yishuihan-001 commented on Feb 19, 2019

@yishuihan-001

['1', '2', '3'].map(parseInt)等价于[parseInt('1',0), parseInt('2',1), parseInt('3',2)]

formattedzzz

formattedzzz commented on Feb 19, 2019

@formattedzzz

总之 radix在[2-9]区间内 Number(string.charAt(0)) 不能大于等于 radix
0x和0X开头的默认都是 16进制字符串转10进制 如果指定了radix 那么都是按常规字符串处理=>0

104 remaining items

GuoguoDad

GuoguoDad commented on May 18, 2022

@GuoguoDad

第二点解释不妥当,当parseInt 第二个参数radix 小于 2 或大于 36时,parseInt直接返回 NaN

Yuweiai

Yuweiai commented on May 25, 2022

@Yuweiai

答案:[1, NaN, NaN]

  • var new_array = arr.map(function callback(currentValue[, index[, array]]) {
     // Return element for new_array 
    }[, thisArg])
  • parseInt(string, radix)
  • parseInt('1', 0)

    如果 radixundefined0 或未指定的,JavaScript 会假定以下情况:

    • 如果输入的 string以 "0x"或 "0X"(一个0,后面是小写或大写的X)开头,那么radix被假定为16,字符串的其余部分被当做十六进制数去解析
    • 如果输入的 string以 "0"(0)开头, radix被假定为8(八进制)或10(十进制)。具体选择哪一个radix取决于实现。ECMAScript 5 澄清了应该使用 10 (十进制),但不是所有的浏览器都支持。因此,在使用 parseInt 时,一定要指定一个 radix
    • 如果输入的 string 以任何其他值开头, radix10 (十进制)
  • parseInt('2', 1)

    • radix 不为 undefined0 或未指定的,且小于 2 或大于 36,返回 NaN
  • parseInt('3', 2)

    • 如果 string 不是指定 radix 中的数字,parseInt 将忽略将字符以及所有后续字符,并返回到该点为止已解析的整数值(允许前导和尾随空格)
    • 如果 string 第一个非空字符就不能转换为指定 radix 中的数字,返回 NaN
Bee-XG

Bee-XG commented on Jun 23, 2022

@Bee-XG

我开始也这么理解:第二个参数需要的范围是2~36之间,如果小于 2 或者大于 36,则 parseInt() 将返回 NaN。但是parseInt(5,4),第二个参数在[2,36]之间,但是结果依旧返回NaN啊。 所以后俩返回NaN,我们是不是又两种角度可以理解呢?

parseInt(5,4) 是因为规定的是按四进制解析 但是5 明显已经超出了 四进制的最大值 所以被解析为 了 NaN

Yangfan2016

Yangfan2016 commented on Aug 3, 2022

@Yangfan2016

好经典的题 360 考过
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt

parseInt(x,y);
// x 为 string
// y 为进制   取值范围 2-36  默认十进制 


yinzuowen

yinzuowen commented on Aug 15, 2022

@yinzuowen

第一眼看到这个题目的时候,脑海跳出的答案是 [1, 2, 3],但是真正的答案是[1, NaN, NaN]

  • 首先让我们回顾一下,map函数的第一个参数callback:

var new_array = arr.map(function callback(currentValue[, index[, array]]) { // Return element for new_array }[, thisArg]) 这个callback一共可以接收三个参数,其中第一个参数代表当前被处理的元素,而第二个参数代表该元素的索引。

  • 而parseInt则是用来解析字符串的,使字符串成为指定基数的整数。
    parseInt(string, radix)
    接收两个参数,第一个表示被处理的值(字符串),第二个表示为解析时的基数。
  • 了解这两个函数后,我们可以模拟一下运行情况
  1. parseInt('1', 0) //radix为0时,且string参数不以“0x”和“0”开头时,按照10为基数处理。这个时候返回1
  2. parseInt('2', 1) //基数为1(1进制)表示的数中,最大值小于2,所以无法解析,返回NaN
  3. parseInt('3', 2) //基数为2(2进制)表示的数中,最大值小于3,所以无法解析,返回NaN

基数的范围是2-36,不在此范围内,parseInt直接返回NaN

xiaogu-123

xiaogu-123 commented on Nov 22, 2022

@xiaogu-123

看了这个题目后专门去研究了parseInt,parseInt的参数 parseInt(String,radix)里的radix根本就没有这么简单,radix根本就不是单纯的进制,详情看我简书的文章 parseInt详解-你以为radix指的进制吗? parseInt

===> 看了老哥的解析瞬间明白了,思路清晰
parseInt("45",5) 当解析45时,4属于范围内,所以得到4,但是5不属于,所以走到这里直接把后面抛弃掉,相当于parseInt("4",5); ---最终得到4。

parseInt("454",5) 当解析454时,4属于范围内,所以得到4,但是5不属于,所以走到这里直接把后面全部抛弃掉, 相当于parseInt("4",5); ---最终得到4。 

parseInt("44",5) 当解析44时,4属于范围内,后面那个4还是在范围内,所以,算作一个整体,属于正常,不进行任何操作   根据进制算法,最终算出,从右往左 45^0+45^1 = 24

parseInt("445",5) 当解析445时,4属于范围内,后面那个4还是在范围内, 但是在后面的5不属于, 所以,5抛弃掉,只取44,相当于 parseInt("44",5); , 根据进制算法,最终算出,从右往左 45^0+45^1 = 24

parseInt("544",5) 当解析544时,5直接不属于范围内,所以全部抛弃掉,只取"", 相当于parseInt("",5); 返回NaN

parseInt("5",5) 当解析5时,5直接不属于范围内,所以全部抛弃掉,只取"", 相当于parseInt("",5); 返回NaN

Bibooo25730

Bibooo25730 commented on May 30, 2023

@Bibooo25730

脑壳疼

xiaogu-123

xiaogu-123 commented on May 30, 2023

@xiaogu-123
ChengYu08

ChengYu08 commented on Nov 16, 2023

@ChengYu08

将字符串解析指定为 指定进制 字符串中的值应该小于 进制的值 不然返回NaN
如果不传 (或者为0) 默认是10进制。小数转10进制 默认向下取整
parseInt("字符串",进制) 意思是将字符串看成 ?进制 解析 然后返回10进制的数

parseInt('100', 2); 000 001 010 011 100 ==>4

parseInt("17",8); 00 01 02 03 04 05 06 07 10 11 12 13 14 15 16 17 ==>15

parseInt("11",2); 00 01 10 11 =》 3

xiaogu-123

xiaogu-123 commented on Nov 16, 2023

@xiaogu-123
gamejoye

gamejoye commented on Aug 12, 2024

@gamejoye

我开始也这么理解:第二个参数需要的范围是2~36之间,如果小于 2 或者大于 36,则 parseInt() 将返回 NaN。但是parseInt(5,4),第二个参数在[2,36]之间,但是结果依旧返回NaN啊。 所以后俩返回NaN,我们是不是又两种角度可以理解呢?

parseInt(5, 4)是NaN是因为 5不能用4进制来表示

xiaogu-123

xiaogu-123 commented on Aug 12, 2024

@xiaogu-123
wangyujie615

wangyujie615 commented on Mar 10, 2025

@wangyujie615

['1','2','3'].map(parseInt)
//==>
['1','2','3'].map((value,index)=>{ parseInt(value,index)})
//parseInt('1',0) radix = 0 是10
//parseInt('2',1) radix < 2 是NaN
//parseInt('3',2) radix = 2 意味着每个位置的最大值是1 只有0 1
console.log(['1', '1', '10','21','33'].map(parseInt))
//输出:1 NaN 2 7 15
//parseInt('1',0) radix = 0 是10 所以输出为1
//parseInt('1',1) radix < 2 是NaN
//parseInt('10',2) radix = 2 意味着每个位置的最大值是1 只有0 1 ==>12^1+02^0 = 2
//parseInt('21',3) radix = 3 意味着每个位置的最大值是2 只有0 1 2 ==>23^1+13^0 = 7
//parseInt('33',4) radix = 4 意味着每个位置的最大值是3 只有0 1 2 3 ==>34^1+34^0 = 15

xiaogu-123

xiaogu-123 commented on Mar 10, 2025

@xiaogu-123
brother-forteen

brother-forteen commented on Mar 10, 2025

@brother-forteen
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @samonxian@zhishaofei3@thinkfish@GuoguoDad@Quesle

        Issue actions

          第 2 题:['1', '2', '3'].map(parseInt) what & why ? · Issue #4 · Advanced-Frontend/Daily-Interview-Question