为什么 parseInt 使用 Array#map 产生 NaN?

IT技术 javascript
2021-01-16 01:36:51

来自Mozilla 开发者网络

[1,4,9].map(Math.sqrt)

将产生:

[1,2,3]

为什么会这样:

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

产生这个:

[1, NaN, NaN]

我已经在 Firefox 3.0.1 和 Chrome 0.3 中进行了测试,作为免责声明,我知道这不是跨浏览器功能(没有 IE)。

我发现以下将达到预期的效果。但是,它仍然不能解释parseInt.

['1','2','3'].map(function(i){return +i;}) // returns [1,2,3]
6个回答

in 的回调函数Array.map三个参数:

您链接到的同一个Mozilla 页面

使用三个参数调用回调:元素的值、元素的索引和正在遍历的 Array 对象。”

所以如果你调用一个parseInt实际需要两个参数的函数,第二个参数将是元素的索引。

在这种情况下,您最终parseInt以基数 0、1 和 2 依次调用第一个与不提供参数相同,因此它基于输入(在本例中为基数 10)进行默认设置。基数 1 是不可能的数基数,而 3 不是基数 2 中的有效数:

parseInt('1', 0); // OK - gives 1
parseInt('2', 1); // FAIL - 1 isn't a legal radix
parseInt('3', 2); // FAIL - 3 isn't legal in base 2 

所以在这种情况下,你需要包装函数:

['1','2','3'].map(function(num) { return parseInt(num, 10); });

或使用 ES2015+ 语法:

['1','2','3'].map(num => parseInt(num, 10));

(在这两种情况下,最好如图所示明确提供基数parseInt,否则它会根据输入猜测基数。在一些较旧的浏览器中,前导 0 会导致它猜测八进制,这往往是有问题的。它仍然会如果字符串以0x.开头,则猜测十六进制。)

map正在传递第二个参数,它(在许多情况下)弄乱了parseInt的基数参数。

如果您使用下划线,您可以执行以下操作:

['10','1','100'].map(_.partial(parseInt, _, 10))

或不带下划线:

['10','1','100'].map(function(x) { return parseInt(x, 10); });

您可以使用Number作为 iteratee 函数来解决此问题

var a = ['0', '1', '2', '10', '15', '57'].map(Number);

console.log(a);

如果没有 new 运算符,Number 可用于执行类型转换。但是,它与 parseInt 不同:它不解析字符串,如果无法转换数字,则返回 NaN。例如:

console.log(parseInt("19asdf"));
console.log(Number("19asf"));

我敢打赌,parseInt 的第二个参数基数会发生一些奇怪的事情。为什么它在使用 Array.map 而不是直接调用它时会中断,我不知道。

//  Works fine
parseInt( 4 );
parseInt( 9 );

//  Breaks!  Why?
[1,4,9].map( parseInt );

//  Fixes the problem
[1,4,9].map( function( num ){ return parseInt( num, 10 ) } );
如果提供的字符串以 0 字符开头,则 parseInt 仅假定八进制。
2021-03-29 01:36:51
哦,是的……没错。它试图根据输入“猜测”基数。对于那个很抱歉。
2021-04-05 01:36:51

您可以使用箭头函数 ES2015/ES6 并将数字传递给 parseInt。基数的默认值为 10

[10, 20, 30].map(x => parseInt(x))

或者您可以明确指定基数以提高代码的可读性。

[10, 20, 30].map(x => parseInt(x, 10))

在上面的示例中,基数显式设置为 10