Javascript parseInt () з провідними нулями


120

Функція розбору Javascript, здається, не працює повністю.

parseInt("01") returns 1
parseInt("02") returns 2
parseInt("03") returns 3
parseInt("04") returns 4
parseInt("05") returns 5
parseInt("06") returns 6
parseInt("07") returns 7
parseInt("08") returns 0
parseInt("09") returns 0

Ви не можете цього пояснити. Спробувати. (jsFiddle)

Редагувати Оскільки на це запитання було задано і відповіли, "особливість" дефолту до восьмигранного радіусу застаріла. [ 1 ] [ 2 ]


29
ви повинні жартувати
georg

6
You can't explain that. Так, ви можете => developer.mozilla.org/uk/JavaScript/Reference/Global_Objects/…
Rocket Hazmat

3
Починаючи з віків, будь-яке число, що починається з 0, являє собою OCTAL, а 0x являє собою Hexa-Decimal. Я вважаю, що це універсально для всіх мов, але я знову можу помилятися.
Selvakumar Arumugam

3
FYI: jsFiddle , краще тестер JavaScript в Інтернеті, ніж w3schools.com/jsref/tryit.asp .
Ракета Хазмат

2
@JohnHartsock Yeh, це тому , що ми обидва були на це повідомлення stackoverflow.com/questions/8761997 / ...
savinger

Відповіді:


181

Це тому, що якщо число починається з '0', воно трактується як основа 8 (восьмерична).

Ви можете примусити базу, передавши базу як другий параметр.

parseInt("09", 10) // 9

Згідно з документами , 2-й параметр є необов’язковим, але не завжди він вважається рівним 10, як ви бачите зі свого прикладу.


1
так, але якщо вважати восьмеричним, він повинен повертатися 11 за 09 замість 0.
Peeyush Kushwaha

2
@PeeyushKushwaha: Інакше. 11в базі 8 знаходиться 9в базі 10. 09не є дійсним базовим номером 8.
Ракета Хазмат

Але я хочу 09 після розбору, чи є щось навпаки
Pardeep Jain

39

Дзвінки parseIntповинні завжди вказувати базу в другому аргументі:

parseInt("08", 10);

Більш ранні версії рядків ласощів JavaScript , починаючи з 0як восьмеричні (якщо не вказано підставу) і ні 08ні 09поважних восьмеричні числа.

З документації на Mozilla :

Якщо значення radix не визначено або 0, JavaScript передбачає наступне:

  • Якщо рядок введення починається з "0x" або "0X", радіакс дорівнює 16 (шістнадцятковий).
  • Якщо рядок введення починається з "0", радіус дорівнює восьми (вісімковий). Ця функція нестандартна, і деякі реалізації навмисно не підтримують її (натомість використовують радіус 10). З цієї причини завжди вказуйте радіус при використанні parseInt .
  • Якщо рядок введення починається з будь-якого іншого значення, радіус дорівнює 10 (десятковий).

Якщо перший символ неможливо перетворити на число, parseInt повертає NaN.

І зі стандарту ECMAScript 3 :

Якщо радікс дорівнює 0 або невизначений, а число рядка починається з цифри 0, а не з x або X , то реалізація може, на свій розсуд, інтерпретувати число як вісімкове або як десятичне. Реалізації рекомендується інтерпретувати числа в цьому випадку як десяткові.

Остання версія JavaScript ( ECMAScript 5 ) відмовляється від такої поведінки , але все ж слід вказати радіус для задоволення старих браузерів.


Оскільки це застаріло, у майбутньому ви будете добре використовувати провідні нулі, чи не так?
Pacerier

15

Є параметр Radix

parseInt(value, base)

Де основа - радіус.

У цьому випадку ви оцінюєте базові 10 (десяткові) числа, тому використовуйте

parseInt(value, 10);

4

Здається, це не зовсім дійсно в нових браузерах. Internet Explorer 9 і 10 повернуть 8, якщо ви виконаєте "parseInt (" 08 ")", тоді як Internet Explorer 8 та попередні версії повернуть 0 (IE10 у режимі диваків також поверне 0).

Остання версія Chrome також повертає 8, тому вони, мабуть, нещодавно змінили трактування.


Так, поведінка змінилася. Я оновлю свою відповідь. developer.mozilla.org/en-US/docs/JavaScript/Reference/…
Вейн

1
Так, Firefox та Chrome остання версія зараз не мають проблем.
mythicalcoder

3

Зараз ця проблема застаріла. Але ви все одно можете використовувати radix в, parseIntщоб перетворити кількість інших баз у базову-10. Наприклад,

var baseTwoNumber = parseInt('0010001', 2);

повернення 17(що є базовою-10 з 0010001).


0

Порада: Як ви тепер знаєте, коли застаріле значення для восьмерики було вимкнено. Ось як це можна виправити у застарілих браузерах

// ES-5 15.1.2.2
if (parseInt('08') !== 8 || parseInt('0x16') !== 22) {
    parseInt = (function (origParseInt) {
        var hexRegex = /^0[xX]/;
        return function parseIntES5(str, radix) {
            str = String(str).trim();
            if (!Number(radix)) {
                radix = hexRegex.test(str) ? 16 : 10;
            }
            return origParseInt(str, radix);
        };
    }(parseInt));
}

PS: якщо ви використовуєте просто постійне число з початковим нулем (замість рядка), воно все ще розглядається як база 8 у всіх поточних браузерах.
Агамемнус

0

Здається, проблема змінилася в більшості браузерів.

Firefox 51.0.1 (64-розрядний)

parseInt("09")   // 9

Chrome 55.0.2883.95 (64-розрядний)

parseInt("09")   // 9

Safari 10.0 (12602.1.50.0.10)

parseInt("09")   // 9

=====

Рекомендована практика

Сказавши це, просто щоб бути безпечнішою і уникати проблем, використовуйте параметр base / radix, як пропонується у прийнятій відповіді .

parseInt("09", 10)    // 9

Додатковий тест

Я просто хотів перевірити це також, якщо аргумент не є рядком. Chrome & Safari дає точний результат. Firefox теж повертає належний результат, але з попередженням.

parseInt(09)     // 9. (Warning: SyntaxError: 09 is not a legal ECMA-262 octal constant)

Якщо значення починається з 0 і є числом, parseInt все одно використовуватиме базу 8. Спробуйте parseInt (020)
sirrocco

Так. Я навіть вказав на запропоновану відповідь. І я знаю кращі практики та погані можливості, яких слід уникати. Тож я і відповів практикою, як і у своїй відповіді.
mythicalcoder
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.