为什么parseInt用Array#map生成NaN?

从Mozilla开发者networking :

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

会产生:

 [1,2,3] 

为什么然后呢:

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

产生这个:

 [1, NaN, NaN] 

我已经在Firefox 3.0.1和Chrome 0.3中进行了testing,只是作为一个免责声明,我知道这不是跨浏览器function(没有IE)。

我发现以下将达到预期的效果。 但是,它仍然没有解释parseInt的错误行为。

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

Array.map的callback函数有三个参数:

从您链接到的同一个Mozilla页面 :

callback被调用三个参数:元素的值,元素的索引和被遍历的数组对象。

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

在这种情况下,您最终依次调用了基数为0,1和2的parseInt 。 第一个与不提供参数相同,所以它默认基于input(在本例中为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); }); 

或使用ES2015 +语法:

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

(在这两种情况下,最好明确地提供一个基数到parseInt ,否则它会根据input猜测基数。在一些老的浏览器中,前导0导致它被猜测为八进制,这往往是有问题的,它仍然会猜测如果string以0x则为hex)。

map传递给第二个参数,这是(在许多情况下)搞乱parseInt的基数参数。

如果你使用下划线,你可以这样做:

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

或者没有下划线:

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

我打赌,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 ) } ); 

你可以使用Number作为迭代函数来解决这个问题:

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

另一个(工作)快速修复:

 var parseInt10 = function(x){return parseInt(x, 10);} ['0', '1', '2', '10', '15', '57'].map(parseInt10); //[0, 1, 2, 10, 15, 57] 

你可以使用箭头functionES2015 / ES6,只是传递给parseInt的数字。 基数的默认值是10

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

或者您可以明确指定基数,以便更好地读取代码。

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

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

parseInt恕我直言,应该避免这个原因。 你可以把它包装起来,使它在这样的环境下更安全:

 const safe = { parseInt: (s, opt) => { const { radix = 10 } = opt ? opt : {}; return parseInt(s, radix); } } console.log( ['1','2','3'].map(safe.parseInt) ); console.log( ['1', '10', '11'].map(e => safe.parseInt(e, { radix: 2 })) );