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

时间:2008-11-04 16:46:53

标签: javascript

来自Mozilla Developer Network

[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]

8 个答案:

答案 0 :(得分:446)

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

来自您链接到的Mozilla page

  使用三个参数调用

回调:元素的值,元素的索引和遍历的Array对象。“

因此,如果您调用实际需要两个参数的函数parseInt,则第二个参数将是元素的索引。

在这种情况下,您最终依次使用基数0,1和2调用parseInt。第一个与不提供参数相同,因此基于输入(在这种情况下为基数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开头,它仍会猜测十六进制。)

答案 1 :(得分:22)

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

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

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

或没有下划线:

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

答案 2 :(得分:15)

您可以使用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"));




答案 3 :(得分:11)

我打算用parseInt的第二个参数radix进行下注。为什么打破使用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 ) } );

答案 4 :(得分:3)

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

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

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

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

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

答案 5 :(得分:1)

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

var parseInt10 = function(x){return parseInt(x, 10);}

['0', '1', '2', '10', '15', '57'].map(parseInt10);
//[0, 1, 2, 10, 15, 57]

答案 6 :(得分:0)

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 }))
);

lodash / fp默认情况下将参数迭代为1以避免这些陷阱。就个人而言,我发现这些变通方法可以创建尽可能多的错误。我认为将parseInt列入黑名单以支持更安全的实施是一种更好的方法。

答案 7 :(得分:0)

你可以这样解决这个问题:

array.map(x => parseInt(x))

示例:

var arr = ["3", "5", "7"];

console.log(
  arr.map(x => parseInt(x))
);