让NaN不一致地映射parseInt

时间:2015-09-01 01:47:37

标签: javascript arrays nan

正在使用一些代码来创建0的数组,并发现只返回一个值NaN而不是0。我在Chrome,Node和Firefox中得到了它。

是什么导致第二个值为NaN

var arr = new Array(32).join(0).split('').map(parseInt)
// prints [0, NaN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
console.dir(arr)

3 个答案:

答案 0 :(得分:26)

那是因为传递给map的函数将使用三个参数调用:

  1. 当前数组项
  2. 该项目的索引
  3. 整个数组
  4. 在这种情况下,该函数是parseInt,它只使用两个参数:

    1. 要解析的字符串
    2. 用于解析字符串的基数
    3. 其他参数将被忽略。
    4. 因此,对于数组中的第二项(即索引1),调用将是

      parseInt("0", 1, ignoredArray)
      

      当基数为1时,会返回NaN

        
          
      • R = ToInt32 radix )。
      •   
      • 如果 R ≠0,那么      
            
        • 如果 R < 2或 R > 36,然后返回 NaN
        •   
      •   

      另请注意,如果您使用较大的数字,例如new Array(99),您会看到NaN从索引37开始。

答案 1 :(得分:9)

.map()函数将三个参数传递给回调,其中两个由parseInt()使用:值和索引(第三个是数组本身)。当索引为1时,任何数字字符串都将是无效值。 parseInt()函数忽略第二个参数0

详细说明:对于第一个元素,parseInt()被调用如下:

parseInt("0", 0)

因为数组值为零且索引为零。在第二次通话中,就是这样:

parseInt("0", 1)

并返回NaN

请注意,如果您对结果全部不太挑剔,那么您可以使用Number构造函数执行您要执行的操作:

var arr = new Array(32).join(0).split('').map(Number);

在ES2015中(最新批准的JavaScript标准,如果我们都非常好,将在所有浏览器中完全实现,如圣诞礼物),您可以使用.fill()函数:

var arr = new Array(31).fill(0);

答案 2 :(得分:6)

映射将三个参数传递给它的函数:

  • 元素;
  • 数组中该元素的索引;和
  • 阵列本身。

parseInt函数将查看前两个函数,将第一个正确地视为字符串,但将第二个视为要使用的基础。当基数既不为零也不在包含范围2..36内时,它返回NaN (1)。如果你有一个包含四十个元素的数组,那么你最后也会看到一堆NaN值:

0, NaN, 0, 0, 0, ... 0, 0, 0, NaN, NaN

如果数字字符串不是零,你也会得到一些非常奇怪的结果,因为数组索引将决定用什么基数来解释它。

要实际修复,您只需提供一个功能,将map 为您提供的内容转换为parseInt 期望的内容(一张地图,我想你可以称之为):

function myParseInt(s,r,a) { return parseInt(s,10); }
var arr = new Array(32).join(0).split('').map(myParseInt)
alert(arr)

您可能还想看一下创建此数组的方式,它实际上最终会变成一个大小为31而不是32的数组。如果您只想要一个'0'个字符数组,你可以使用:

var arr = new Array(32).fill('0')

假设您有一个支持ECMAScript 2015的浏览器,截至本答复时,它是Safari,Firefox和Chrome桌面。

(1)基数为零是处理十六进制前缀等内容的默认情况。

一个基数在纯粹的位置系统中是没有意义的(其中每个数字乘以基数的幂并累加)因为唯一允许的数字将是0,所以每个地方值将是零乘以1n。换句话说,基础系统中唯一可能的数字将为零。

236的基础因此更为明智。