Як я можу розібратися в синтаксичному синтаксичному виконанні JavaScript?


283

Спробуйте виконати таке в 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"в базовій-8, функція повертає нуль. Вам подобається чи ні, це за задумом .

Що таке обхідні шляхи?

Примітка. Для повноти я збираюся опублікувати рішення, але це рішення, яке я ненавиджу, тому, будь ласка, опублікуйте інші / кращі відповіді.


Оновлення:

5-е видання стандарту JavaScript ( ECMA-262 ) вносить переломну зміну, яка виключає таку поведінку. Mozilla має хорошу рецензію .


21
Крок 1) Зробіть собі прихильність і завжди включайте радіус, як згадувалося в попередніх відповідях, а також у книзі Дуга. Крок 2) Якщо ви серйозно ставитеся до вивчення JavaScript, то отримайте собі копію книги Дуга. Це неоціненний. Поки що моя книжка про фаворити. Ось огляд fyi: realtech.burningbird.net/learning-javascript/basics/…
fuentesjr

8
У веб-переглядачах, сумісних з ECMAScript 5-го видання, таких як Internet Explorer 9, базовий параметр за замовчуванням 10(десятковий), за винятком випадків, коли число для розбору встановлено з префіксом 0x, наприклад 0xFF, у цьому випадку базовий параметр за замовчуванням до 16. Сподіваємось, одного дня ця проблема буде віддаленою пам’яттю.
Енді Е

2
Як щодо +'08' === 8? Правда! Можливо, вам справді потрібен parseIntваш справжній код, але не вище.
kojiro

1
а) це не помилка, виправте заголовок б)Number('08')
OnTheFly

4
@portman: "5-е видання ... вводить переломну зміну, яка виключає таку поведінку" Напевно, варто зазначити, що навіть у 3-му виданні (13 років тому) реалізація "заохочувалась" цього не робити: "Коли радікс є 0або undefinedі рядок починається з 0цифри, за якою не йде xабо X, або реалізація може, на власний розсуд, інтерпретувати число як вісімкове або як десяткове. Реалізації рекомендується інтерпретувати числа в цьому випадку як десяткові. " ( мій акцент)
TJ Crowder

Відповіді:


329

Це звичайна JavaScript-скрипка з простим рішенням:

Просто вкажіть основу , або "radix", наприклад:

parseInt('08',10); // 8

Ви також можете використовувати номер :

Number('08'); // 8

57
Номер . Славний.
Портман

10
Цифри потребують котирування біля 08. Також просто попередимо, що номер ('08 .123 ') дасть 8.123 як його вихід. Якщо ви дійсно хочете ціле число, не використовуйте число (або відповідність шаблону для введення даних, щоб забезпечити лише цілі числа).
Jason S

3
Номер (08); дає мені 8 у Firefox та IE.
Паоло Бергантіно

3
він не входить до стандарту ECMAscript. Я тестую JSDB, який використовує Spidermonkey 1.7 (= двигун Firefox JS), і скаржиться "08 не є законною восьмиконстантою ECMA-262"
Jason S

5
Все-таки використовуйте "08" у лапках. 08 не відповідає стандарту ECMA-262, і не гарантується успіх без попереджень та / або помилок та / або конкретної визначеної поведінки.
Jason S

43

Якщо ви знаєте, що ваше значення буде знаходитись у підписаному 32-бітовому цілому діапазоні, тоді ~~xзробите правильну справу у всіх сценаріях.

~~"08" === 8
~~"foobar" === 0
~~(1.99) === 1
~~(-1.99)  === -1

Якщо ви шукаєте бінарне не ( ~), специфікація вимагає перетворення "ToInt32" для аргументу, який робить очевидне перетворення в Int32 і задається для примусового NaNзначення до нуля.

Так, це неймовірно хакі, але так зручно ...


2
Чому дві операції, коли однієї двійкової або було б достатньо?
Олег Вікторович Волков

@ Олег, чому одного вистачить?
Себастьян

3
@SebastianGodelet, | 0.
Олег Вікторович Волков

@Grodriguez, а коли 0 в | 0 - це рядок?
Олег Вікторович Волков

Все це питання стосується альтернативи parseInt для перетворення рядків у цілі числа. Таким чином: завжди.
Grodriguez

24

З документації parseInt використовуйте необов’язковий аргумент radix, щоб вказати base-10:

parseInt('08', 10); //equals 8
parseInt('09', 10); //equals 9

Це вражає мене педантичним, заплутаним та багатослівним (справді, додатковим аргументом у кожному окремому аналізі?), Тож я сподіваюся, що є кращий шлях.


6
якщо вам не подобається Verbosity, тоді просто зробіть свою власну функцію, яка викликає вбудовану функцію та заповнює аргументи, які ви завжди підтримуєте постійними.
Jason S

3
Riiiiiiight, тому що це не так, як кожна людина в StackOverflow залякує вас за написання функції parseIntB10. Написання власної функції обгортки - жахлива ідея для цієї мети.
Стефан Кендалл

2
@iftrue: Я думаю, ти пропустив мою думку. Я особисто не проти просто робити розбір (someString, 10) скрізь, щоб переконатись, що я змушую базу 10. ОП, схоже, не подобається такому підходу, тому я запропонував альтернативу, яку я особисто не використовував би, але, можливо, він відповідає його потреби. (це, мабуть, думка, що стоїть за JQuery: зробіть це зручним, додавши додаткову складність. Я не використовую JQuery, але багато людей вважають це корисним.)
Jason S

4
Насправді дуже важливо обернути parseIntдля зручного використання у функціональних виразах, як mapin ["7","4","09","5"].map(parseInt); Mapпередасть індекс елемента в масиві як другий аргумент, який буде інтерпретуватися parseIntяк база, якщо ви не завернете його.
Plynx

11
function parseDecimal(s) { return parseInt(s, 10); }

редагувати: зробити власну функцію - робити те, що ви дійсно хочете, - це лише варіант, якщо вам не подобається постійно додавати ", 10" у виклик parseInt (). Недоліком є ​​нестандартна функція: зручніше для вас, якщо ви багато використовуєте, але, можливо, більш заплутано для інших.


10

Вкажіть базу:

var number = parseInt(s, 10);

Ух ти, хлопці, швидко. У мене навіть була відповідь у буфері обміну. Ви підключені безпосередньо до Інтернету, нео-стилі?
Портман

1
Чому диявол це не дефолт на базі 10
Том Галлен

2
Можливо, тому, що це в першу чергу не означає функцію перетворення рядка-> число, а функцію, яка зчитує число з базового b рядка числа.
artistoex

2
він за замовчуванням базу 10, але провідні нулі - це широко розповсюджений спосіб позначення восьмикутників.
Натан

7

Було б дуже неслухняно замінювати parseInt версією, яка передбачає десятковий, якщо у нього немає другого параметра? (Примітка - не перевірено)

parseIntImpl = parseInt
parseInt = function(str, base){return parseIntImpl(str, base ? base : 10)}

2
так, це було б неслухняно - воно порушило б інший код, який спирався на стандартну поведінку.
jes5199

4
Це правда, але цього мало. Це також не стандартне поведінка - восьмерична підтримка необов’язкова.
Ендрю Даффі

2
Але ви також скидаєте шестигранну підтримку, яка не є обов'язковою, чи не так? Це завжди має бути правдою: parseInt("0xFFFFFF") === 16777215але з вашим неслухняним злому це вже не працюєparseInt("0xFFFFFF") === 0
Тімо


6

Ви можете також замість того, щоб використовувати parseFloat або parseInt, використовувати одинарний оператор ( + ).

+"01"
// => 1

+"02"
// => 2

+"03"
// => 3

+"04"
// => 4

+"05"
// => 5

+"06"
// => 6

+"07"
// => 7

+"08"
// => 8

+"09"
// => 9

і на добру міру

+"09.09"
// => 9.09

MDN-посилання

Оператор unary плюс передує його операнду і оцінює його операнду, але намагається перетворити його в число, якщо його ще немає. Хоча унарне заперечення (-) також може конвертувати не числа, унарний плюс - це найшвидший і бажаний спосіб перетворення чогось у число , оскільки він не виконує жодних інших операцій над числом.



4

Якщо ви зробили купу кодування вже за допомогою parseInt і не хочете додавати "10" до всього, ви можете просто змінити функцію, щоб базову 10 зробити за замовчуванням:

window._oldParseInt = window.parseInt;
window.parseInt = function(str, rad) {
    if (! rad) {
        return _oldParseInt(str, 10);
    }
    return _oldParseInt(str, rad);
};

Це може заплутати більш пізнього читача, тому зробити функцію parseInt10 () може бути більш зрозумілим. Особисто я вважаю за краще використовувати просту функцію, ніж постійно додавати "10" - просто створює більше можливостей для помилок.


0

Цю проблему неможливо повторити в останніх Chrome чи Firefox (2019).

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