为什么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 })) );