String na liczbę w JavaScripcie: parseInt, Number i operator +

Cztery sposoby na zamianę stringa w liczbę w JavaScripcie, różnice na „42px”, „3,99” i pustym stringu, obsługa NaN oraz metoda właściwa dla każdego przypadku.

String na liczbę w JavaScripcie: parseInt, Number i operator +
Szybka odpowiedź

Użyj Number(chaine), gdy string ma być w całości liczbą („42”, „3.99”): przy najmniejszym obcym znaku zwraca NaN. Użyj parseInt(chaine, 10) albo parseFloat(chaine), żeby wyciągnąć liczbę z początku stringa w rodzaju „42px”. Wynik zawsze sprawdzaj przez Number.isNaN(), zanim policzysz.

Wartość odczytana z pola formularza, z atrybutu HTML, z adresu URL albo ze źle otypowanego pliku JSON zawsze przychodzi jako string. Zanim cokolwiek policzysz, trzeba ją zamienić na liczbę. JavaScript daje na to cztery sposoby, a każdy inaczej reaguje na „42px”, „3,99” czy pusty string. Oto co naprawdę zwraca każdy z nich, sprawdzone pod Node.js 22.

Cztery metody w jednej tabeli

String parseInt(s, 10) parseFloat(s) Number(s) +s
"42" 42 42 42 42
"3.99" 3 3.99 3.99 3.99
"42px" 42 42 NaN NaN
" 42 " 42 42 42 42
"" (pusty) NaN NaN 0 0
"12,5" 12 12 NaN NaN
"1e3" 1 1000 1000 1000
"0x1f" 0 (wymuszona podstawa 10) 0 31 31
"abc" NaN NaN NaN NaN
"Infinity" NaN Infinity Infinity Infinity
null NaN NaN 0 0
undefined NaN NaN NaN NaN

Rysują się dwie rodziny. parseInt i parseFloat wyciągają: czytają string od początku, zatrzymują się na pierwszym znaku, który nie jest cyfrą, i zwracają to, co zdążyły przeczytać. Number() i operator + konwertują wszystko albo nic: cały string musi przedstawiać liczbę, inaczej wychodzi NaN. Jeden wyjątek kłuje: pusty string jest dla nich zerem.

parseInt(): liczba całkowita z początku stringa

javascript
parseInt('42', 10);      // 42
parseInt('42px', 10);    // 42  : zatrzymuje się na „p”
parseInt('3.99', 10);    // 3   : część dziesiętna jest ucinana, nie zaokrąglana
parseInt('  42  ', 10);  // 42  : spacje wokół są tolerowane
parseInt('abc', 10);     // NaN : brak cyfry na początku
parseInt('', 10);        // NaN

Drugi argument to podstawa (czyli radix). Wynosi 10 dla liczby dziesiętnej, 16 dla szesnastkowej, 2 dla binarnej:

javascript
parseInt('ff', 16);   // 255
parseInt('101', 2);   // 5
parseInt('0x1f');     // 31 : bez podstawy przedrostek 0x przełącza na szesnastkowy
parseInt('08');       // 8  : nowoczesne silniki nie czytają już „08” ósemkowo

Jawne podanie podstawy, parseInt(s, 10), nie jest już konieczne dla zer wiodących od czasów ES5, ale to nadal dobry nawyk: pokazuje intencję i neutralizuje przypadek 0x.

parseFloat(): liczba dziesiętna z początku stringa

javascript
parseFloat('3.99');     // 3.99
parseFloat('12.5px');   // 12.5
parseFloat('.5');       // 0.5
parseFloat('1e3');      // 1000 : notacja naukowa jest rozumiana
parseFloat('3,99');     // 3    : przecinek przerywa czytanie
parseFloat('abc');      // NaN

parseFloat nie ma argumentu podstawy: zawsze czyta dziesiętnie. To funkcja do wyciągania miary ze stringa CSS („12.5px”, „1.5rem”) albo ze swobodnego tekstu.

Number(): konwersja ścisła

javascript
Number('42');       // 42
Number('3.99');     // 3.99
Number('  42  ');   // 42  : spacje i znaki końca linii wokół są pomijane
Number('42px');     // NaN : jeden znak za dużo i wszystko pada
Number('');         // 0   : uwaga
Number(' ');        // 0   : tak samo
Number(null);       // 0
Number(undefined);  // NaN
Number(true);       // 1
Number('0x1f');     // 31  : szesnastkowy, binarny (0b) i ósemkowy (0o) z przedrostkiem są przyjmowane

Number() to konwersja, jakiej potrzebujesz dla wartości, która ma być liczbą i niczym więcej: ceny, ilości, identyfikatora. Jeśli użytkownik wpisał „12 euros”, dostajesz NaN i możesz mu o tym powiedzieć, zamiast policzyć na 12 bez świadomości.

Jednoargumentowy operator +: Number() na jednym znaku

javascript
+'42';     // 42
+'';       // 0
+'abc';    // NaN
'42' * 1;  // 42  : mnożenie też wymusza konwersję
'42' - 0;  // 42
'3' + '4'; // '34' : dodawanie natomiast skleja!

+ postawiony przed wartością robi dokładnie to samo co Number(). Jest krótki, bardzo częsty w istniejącym kodzie i łatwo go przeoczyć przy czytaniu: +valeur wygląda jak literówka. We wspólnym kodzie Number(valeur) mówi to samo wyraźniej. I nigdy nie konwertuj dwuargumentowym dodawaniem: '3' + '4' daje string '34'.

Poprawna obsługa NaN

NaN (Not a Number) to wynik każdej nieudanej konwersji. Ma podstępną własność: nie równa się niczemu, nawet samemu sobie.

javascript
const n = Number('abc');

n === NaN;          // false, zawsze
Number.isNaN(n);    // true  : właściwy sposób sprawdzania
isNaN('abc');       // true  : ale isNaN najpierw konwertuje swój argument...
Number.isNaN('abc');// false : ... podczas gdy Number.isNaN sprawdza tylko prawdziwe NaN

Zwykły schemat: skonwertuj, sprawdź, podstaw wartość domyślną albo zgłoś błąd.

toNumber.js
function toNumber(valeur, defaut = 0) {
  const n = Number(String(valeur).trim());
  return Number.isNaN(n) ? defaut : n;
}

toNumber('42');    // 42
toNumber('42px');  // 0  (wartość domyślna)
toNumber('', 10);  // 0  : pusty string daje 0, a nie wartość domyślną

Ostatnia linia przypomina o pułapce pustego stringa: jeśli puste pole ma być traktowane jako „nie podano”, sprawdź je przed konwersją.

javascript
function toNumberStrict(valeur) {
  const s = String(valeur).trim();
  if (s === '') return NaN;
  return Number(s);
}

Przypadek francuski: przecinek dziesiętny

Żadna z czterech metod nie rozumie „12,5”. Number zwraca NaN, a parseFloat zatrzymuje się na przecinku i zwraca 12, co jest gorsze: program leci dalej z błędną wartością. Znormalizuj wpis przed konwersją.

parseFr.js
function parseFr(chaine) {
  const normalisee = String(chaine)
    .replace(/\s/g, '')   // usuwa spacje tysięcy: „1 234,56”
    .replace(',', '.');   // przecinek dziesiętny -> kropka
  return Number(normalisee);
}

parseFr('12,5');       // 12.5
parseFr('1 234,56');   // 1234.56
parseFr('12.5');       // 12.5 : kropka nadal jest przyjmowana

W formularzu problem znika dzięki <input type="number">: przeglądarka pokazuje francuskiemu użytkownikowi przecinek, ale w value przekazuje zawsze kropkę.

Sprawdzenie, czy string jest liczbą

Żeby wiedzieć, czy string przedstawia liczbę, zanim jej użyjesz, połącz ścisłą konwersję z Number.isFinite, które odrzuca NaN i Infinity.

javascript
function estNumerique(chaine) {
  const s = String(chaine).trim();
  return s !== '' && Number.isFinite(Number(s));
}

estNumerique('42');       // true
estNumerique('3.99');     // true
estNumerique('42px');     // false
estNumerique('');         // false
estNumerique('Infinity'); // false

A żeby po konwersji odróżnić liczbę całkowitą od dziesiętnej: Number.isInteger(42) daje true, a Number.isInteger(3.99) daje false.

Duże liczby całkowite: gdy Number już nie wystarcza

Number przedstawia dokładnie liczby całkowite do 253 − 1 (9 007 199 254 740 991). Powyżej precyzja znika bez ostrzeżenia: 64-bitowy identyfikator z bazy danych albo bardzo wysoka kwota w centach mogą zostać przekłamane.

javascript
Number('9007199254740993');   // 9007199254740992 : ostatnia cyfra się zmieniła
BigInt('9007199254740993');   // 9007199254740993n : dokładnie
Number.MAX_SAFE_INTEGER;      // 9007199254740991

BigInt nie miesza się z Number w obliczeniach i nie przyjmuje części dziesiętnej; zostaw go do identyfikatorów i naprawdę dużych liczb całkowitych.

Którą metodę wybrać?

  • Wartość ma być liczbą i niczym więcej (cena, ilość, identyfikator): Number(), po odsianiu pustego stringa.
  • Trzeba wyciągnąć liczbę z tekstu („12.5px”, „3 articles”): parseFloat() dla dziesiętnej, parseInt(s, 10) dla całkowitej.
  • Dane wpisuje użytkownik francuski: znormalizuj przecinek i spacje, a potem Number().
  • Czytasz kod z +valeur: to jest Number(valeur). Zostaw, jeśli zespół tak pisze, ale nigdy nie konwertuj dodawaniem '3' + '4'.
  • W każdym przypadku: sprawdź wynik przez Number.isNaN() albo Number.isFinite(), zanim policzysz.

Operacja odwrotna, czyli zamiana liczby na czytelny string z dwoma miejscami po przecinku albo z separatorem tysięcy, jest opisana w tekście Formatowanie liczb w JavaScripcie. Podstawy języka wyjaśnia rozdział Zmienne i typy danych z kursu: tłumaczy, dlaczego string i liczba to dwa osobne typy.

Częste błędy

Pominięcie podstawy w parseInt parseInt("08") daje 8 we wszystkich nowoczesnych silnikach, ale parseInt("0x1f") daje 31: string zostaje odczytany szesnastkowo. Zawsze podawaj podstawę: parseInt(chaine, 10).
Liczenie na francuski przecinek dziesiętny Number("12,5") zwraca NaN, a parseFloat("12,5") zwraca 12. Zamień przecinek na kropkę przed konwersją.
Sprawdzanie NaN przez === NaN === NaN jest fałszem. Używaj Number.isNaN(valeur), nigdy bezpośredniego porównania.
Mylenie pustego stringa z zerem Number("") i +"" dają 0, a nie NaN. Puste pole formularza staje się więc cichym zerem: sprawdź chaine.trim() === "" przed konwersją.

JavaScript

Damien Flandrin Web developer od 2010 roku, twórca Gekkode i Email Impact. Każdy artykuł jest sprawdzany na prawdziwym projekcie przed publikacją. Kontakt
Newsletter

Nowe testy, poradniki i projekty — e-mailem.

Powtarzalne testy, wersjonowany kod, datowane wyniki. Nigdy spamu.