Почему parseInt дает NaN с картой Array #?
В 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]
Ответы
Ответ 1
Функция обратного вызова в Array.map
имеет три параметра:
На той же странице Mozilla, с которой вы связались:
callback вызывается с тремя аргументами: значением элемента, индексом элемента и объектом Array. "
Поэтому, если вы вызываете функцию parseInt
которая фактически ожидает два аргумента, второй аргумент будет индексом элемента.
В этом случае вы в конечном итоге вызываете parseInt
с помощью radix 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));
(В обоих случаях лучше явно предоставить radix для parseInt
как показано на рисунке, поскольку в противном случае он догадывается о базисе на основе ввода. В некоторых старых браузерах ведущее 0 заставляло его угадать восьмеричное, что, как правило, было проблематичным. еще гадайте hex, если строка начинается с 0x
.)
Ответ 2
map
проходит по второму аргументу, который (во многих случаях) испортил parseInt
параметр radix.
Если вы используете подчеркивание, вы можете:
['10','1','100'].map(_.partial(parseInt, _, 10))
Или без подчеркивания:
['10','1','100'].map(function(x) { return parseInt(x, 10); });
Ответ 3
Я собираюсь сделать ставку на то, что это что-то фанковое происходит с параметром parseInt 2nd, 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
Вы можете решить эту проблему, используя Number в качестве функции iteratee:
var a = ['0', '1', '2', '10', '15', '57'].map(Number);
console.log(a);
Ответ 5
Вы можете использовать функцию стрелки ES2015/ES6 и просто передать номер в parseInt. Значение по умолчанию для radix будет 10
[10, 20, 30].map(x => parseInt(x))
Или вы можете явно указать radix для лучшей читаемости вашего кода.
[10, 20, 30].map(x => parseInt(x, 10))
В примере выше radix явно установлен на 10
Ответ 6
другое (рабочее) быстрое исправление:
var parseInt10 = function(x){return parseInt(x, 10);}
['0', '1', '2', '10', '15', '57'].map(parseInt10);
//[0, 1, 2, 10, 15, 57]
Ответ 7
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 }))
);