获取 NaN 不一致地映射 parseInt

Getting NaN inconsistently mapping parseInt

正在使用一些代码来创建 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)

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

时忽略第二个参数

详细说明:对于第一个元素,parseInt() 是这样调用的:

parseInt("0", 0)

因为数组值为零,索引为零。在第二次调用时,是这样的:

parseInt("0", 1)

还有那个 returns NaN.

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

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

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

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

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

  1. 当前数组项
  2. 该项目的索引
  3. 整个数组

在这种情况下,该函数是 parseInt,它只使用两个参数:

  1. 要解析的字符串
  2. 用于解析字符串的基数
  3. 其他参数将被忽略。

因此,对于数组中的第 2 项(即索引 1),调用将是

parseInt("0", 1, ignoredArray)

当基数为1时,返回NaN

  • Let R = ToInt32(radix).
  • If R ≠ 0, then
    • If R < 2 or R > 36, then return NaN.

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

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

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

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

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

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

要真正解决这个问题,您只需提供一个函数,将map给您的内容翻译成parseInt expects(一张地图地图,我猜你可以叫它):

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-desktop 截至本回答时。


(1) 以零为底是处理十六进制前缀之类的默认情况。

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

因此,从 236 的碱基更合理。