Как обойти восьмеричное поведение синтаксического анализа JavaScript?
попробуйте выполнить следующее В JavaScript:
parseInt('01'); //equals 1
parseInt('02'); //equals 2
parseInt('03'); //equals 3
parseInt('04'); //equals 4
parseInt('05'); //equals 5
parseInt('06'); //equals 6
parseInt('07'); //equals 7
parseInt('08'); //equals 0 !!
parseInt('09'); //equals 0 !!
Я только что узнал, что JavaScript думает, что ведущий ноль указывает на восьмеричное целое число, а так как нет "8"
или "9"
в base-8 функция возвращает ноль. Нравится тебе это или нет,это.
какие обходные пути?
Примечание: Для полноты картины, я выложу решение, но это решение, которое я ненавижу, так пожалуйста, опубликуйте другие / лучшие ответы.
обновление:
5-е издание стандарта JavaScript (ECMA-262) вводит критическое изменение, которое устраняет это поведение. Mozilla имеет хороший написать.
9 ответов:
если вы знаю ваше значение будет в 32-битном целочисленном диапазоне со знаком, затем
~~x
будет делать правильные вещи во всех сценариях.~~"08" === 8 ~~"foobar" === 0 ~~(1.99) === 1 ~~(-1.99) === -1
если вы посмотрите двоичный не (
~
), спецификация требует преобразования "ToInt32" для аргумента, который делает очевидное преобразование в Int32 и указывается для принужденияNaN
значения до нуля.Да, это невероятно hackish, но так удобно...
С parseInt documentation используйте необязательный параметр основание системы счисления указывать основание-10:
parseInt('08', 10); //equals 8 parseInt('09', 10); //equals 9
Это кажется мне педантичным, запутанным и многословным (действительно, дополнительный аргумент в каждом отдельном синтаксическом анализе?) поэтому я надеюсь, что есть лучший способ.
function parseDecimal(s) { return parseInt(s, 10); }
edit: создание собственной функции, чтобы делать то, что вы действительно хотите,это просто вариант, если вам не нравится добавлять", 10" все время к вызову parseInt (). Он имеет тот недостаток, что является нестандартной функцией: более удобной для вас, если вы используете ее много, но, возможно, более запутанной для других.
было бы очень непослушно заменить parseInt на версию, которая предполагает decimal, если у нее нет второго параметра? (примечание - не проверено)
parseIntImpl = parseInt parseInt = function(str, base){return parseIntImpl(str, base ? base : 10)}
Если вы уже сделали кучу кодирования с помощью parseInt и не хотите добавлять ",10" ко всему, вы можете просто переопределить функцию, чтобы сделать base 10 по умолчанию:
window._oldParseInt = window.parseInt; window.parseInt = function(str, rad) { if (! rad) { return _oldParseInt(str, 10); } return _oldParseInt(str, rad); };
это может запутать более позднего читателя, поэтому создание функции parseInt10() может быть более понятным. Лично я предпочитаю использовать простую функцию,чем постоянно добавлять", 10" - просто создает больше возможностей для ошибок.
вы также можете вместо использования parseFloat или parseInt использовать унарный оператор (+).
+"01" // => 1 +"02" // => 2 +"03" // => 3 +"04" // => 4 +"05" // => 5 +"06" // => 6 +"07" // => 7 +"08" // => 8 +"09" // => 9
и
+"09.09" // => 9.09
унарный оператор plus предшествует своему операнду и вычисляет его операнд, но пытается преобразовать его в число, если это еще не так. Хотя унарное отрицание ( - ) также может преобразовывать не-числа, унарный плюс является самым быстрым и предпочтительный способ преобразования чего-то в число, потому что он не выполняет никаких других операций с номером.