Почему parseInt дает NaN с картой Array #? - PullRequest
267 голосов
/ 04 ноября 2008

Из Сети разработчиков 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]

Ответы [ 7 ]

446 голосов
/ 04 ноября 2008

Функция обратного вызова в 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.)

22 голосов
/ 11 ноября 2014

map передает второй аргумент, который (во многих случаях) портит параметр радиуса parseInt.

Если вы используете подчеркивание, вы можете сделать:

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

или без подчеркивания:

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

15 голосов
/ 12 ноября 2016

Вы можете решить эту проблему, используя Number в качестве функции iteratee:

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

console.log(a);

Без нового оператора Number можно использовать для преобразования типов. Однако он отличается от parseInt: он не анализирует строку и возвращает NaN, если число не может быть преобразовано. Например:

console.log(parseInt("19asdf"));
console.log(Number("19asf"));
11 голосов
/ 04 ноября 2008

Держу пари, что что-то странное происходит со вторым параметром 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 ) } );
3 голосов
/ 17 августа 2016

Вы можете использовать функцию стрелки ES2015 / ES6 и просто передать число в parseInt. Значение по умолчанию для radix будет 10

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

Или вы можете явно указать radix для лучшей читабельности вашего кода.

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

В приведенном выше примере radix явно установлен на 10

1 голос
/ 12 августа 2015

другое (рабочее) быстрое исправление:

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

['0', '1', '2', '10', '15', '57'].map(parseInt10);
//[0, 1, 2, 10, 15, 57]
0 голосов
/ 16 октября 2017

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 в пользу более безопасной реализации - лучший подход.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...