Из Сеть разработчиков 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]
Или используйте .map(Number).
вы можете arr.map (Math.floor), если вам нужны целые числа без функции, созданной вручную.
@Nikolai user669677 отличные предложения! Я бы поддержал это в ответе
может ли кто-нибудь объяснить, почему parseInt правильно анализирует первое число и делает ошибку не для первого индекса
См. Также это отличное объяснение здесь: wsvincent.com/javascript-parseint-map
ответ здесь: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Держу пари, что со вторым параметром 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 ) } );
parseInt предполагает восьмеричное число только в том случае, если предоставленная строка начинается с символа 0.
О, да ... верно. Он пытается «угадать» основание системы счисления на основе входных данных. Прости за это.
Функция обратного вызова в Array.map имеет параметры три:
Из того же Страница Mozilla, с которым вы связались:
callback is invoked with three arguments: the value of the element, the index of the element, and the Array object being traversed."
Поэтому, если вы вызываете функцию 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 передает второй аргумент, который (во многих случаях) портит параметр radix parseInt.
Если вы используете подчеркивание, вы можете:
['10','1','100'].map(_.partial(parseInt, _, 10))
Или без подчеркивания:
['10','1','100'].map(function(x) { return parseInt(x, 10); });
другое (рабочее) быстрое исправление:
var parseInt10 = function(x){return parseInt(x, 10);}
['0', '1', '2', '10', '15', '57'].map(parseInt10);
//[0, 1, 2, 10, 15, 57]
Вы можете использовать стрелочную функцию ES2015 / ES6 и просто передать номер в parseInt. Значение по умолчанию для системы счисления будет 10.
[10, 20, 30].map(x => parseInt(x))
Или вы можете явно указать систему счисления для лучшей читаемости вашего кода.
[10, 20, 30].map(x => parseInt(x, 10))
В примере выше основание системы счисления явно установлено на 10
Вы можете решить эту проблему, используя Число в качестве функции итерации:
var a = ['0', '1', '2', '10', '15', '57'].map(Number);
console.info(a);Без оператора new для преобразования типа можно использовать Number. Однако он отличается от parseInt: он не анализирует строку и возвращает NaN, если число не может быть преобразовано. Например:
console.info(parseInt("19asdf"));
console.info(Number("19asf"));parseInt ИМХО следует избегать именно по этой причине. Вы можете обернуть его, чтобы сделать его более безопасным в следующих случаях:
const safe = {
parseInt: (s, opt) => {
const { radix = 10 } = opt ? opt : {};
return parseInt(s, radix);
}
}
console.info( ['1','2','3'].map(safe.parseInt) );
console.info(
['1', '10', '11'].map(e => safe.parseInt(e, { radix: 2 }))
);lodash / fp ограничивает итерационные аргументы до 1 по умолчанию, чтобы избежать этих ошибок. Лично я нашел эти обходные пути, чтобы создавать столько ошибок, сколько их можно избежать. Внесение parseInt в черный список в пользу более безопасной реализации, на мой взгляд, является лучшим подходом.
Для ленивых: используйте
.map(parseFloat), потому что он принимает только один параметр.