parseInt ou Number: converter uma string num número em JavaScript

Quatro maneiras de converter uma string em número em JavaScript, as suas diferenças perante «42px», «3,99» ou uma string vazia, o tratamento de NaN e o método a escolher em cada caso.

Converter uma string em número em JavaScript: parseInt e Number
Resposta rápida

Usa Number(chaine) para converter uma string que tenha de ser inteiramente numérica («42», «3.99»): devolve NaN ao mínimo carácter parasita. Usa parseInt(chaine, 10) ou parseFloat(chaine) para extrair o número no início de uma string como «42px». Verifica sempre o resultado com Number.isNaN() antes de calcular.

Um valor lido de um campo de formulário, de um atributo HTML, de um URL ou de um ficheiro JSON mal tipado chega sempre em forma de string. Antes de calcular, é preciso convertê-lo em número. O JavaScript oferece quatro maneiras de o fazer, e nenhuma reage da mesma forma perante «42px», «3,99» ou uma string vazia. Eis o que cada uma devolve realmente, verificado em Node.js 22.

Os quatro métodos numa tabela

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
"" (vazia) NaN NaN 0 0
"12,5" 12 12 NaN NaN
"1e3" 1 1000 1000 1000
"0x1f" 0 (base 10 forçada) 0 31 31
"abc" NaN NaN NaN NaN
"Infinity" NaN Infinity Infinity Infinity
null NaN NaN 0 0
undefined NaN NaN NaN NaN

Desenham-se duas famílias. parseInt e parseFloat extraem: leem a string desde o início, param no primeiro carácter que não é um algarismo e devolvem o que leram. Number() e o operador + convertem tudo ou nada: a string inteira tem de representar um número, senão sai NaN. Uma exceção que custa a engolir: a string vazia vale 0 para eles.

parseInt(): o inteiro no início da string

javascript
parseInt('42', 10);      // 42
parseInt('42px', 10);    // 42  : para no «p»
parseInt('3.99', 10);    // 3   : a parte decimal é ignorada, não arredondada
parseInt('  42  ', 10);  // 42  : os espaços à volta são tolerados
parseInt('abc', 10);     // NaN : nenhum algarismo no início
parseInt('', 10);        // NaN

O segundo argumento é a base (ou radix). Vale 10 para um número decimal, 16 para o hexadecimal, 2 para o binário:

javascript
parseInt('ff', 16);   // 255
parseInt('101', 2);   // 5
parseInt('0x1f');     // 31 : sem base, o prefixo 0x faz passar para hexadecimal
parseInt('08');       // 8  : os motores modernos já não leem «08» em octal

Escrever a base explicitamente, parseInt(s, 10), já não é indispensável por causa dos zeros iniciais desde o ES5, mas continua a ser o bom hábito: torna a intenção legível e neutraliza o caso 0x.

parseFloat(): o número decimal no início da string

javascript
parseFloat('3.99');     // 3.99
parseFloat('12.5px');   // 12.5
parseFloat('.5');       // 0.5
parseFloat('1e3');      // 1000 : a notação científica é compreendida
parseFloat('3,99');     // 3    : a vírgula interrompe a leitura
parseFloat('abc');      // NaN

parseFloat não tem argumento de base: lê sempre em decimal. É a função a escolher para extrair uma medida de uma string CSS («12.5px», «1.5rem») ou de um texto livre.

Number(): a conversão estrita

javascript
Number('42');       // 42
Number('3.99');     // 3.99
Number('  42  ');   // 42  : espaços e mudanças de linha à volta são ignorados
Number('42px');     // NaN : um único carácter a mais e tudo falha
Number('');         // 0   : atenção
Number(' ');        // 0   : idem
Number(null);       // 0
Number(undefined);  // NaN
Number(true);       // 1
Number('0x1f');     // 31  : hexadecimal, binário (0b) e octal (0o) com prefixo são aceites

Number() é a conversão que queres para um valor que tem de ser um número e mais nada: um preço, uma quantidade, um identificador. Se o utilizador escreveu «12 euros», recebes NaN e podes dizer-lho, em vez de calcular com 12 sem saber.

O operador unário +: Number() num carácter

javascript
+'42';     // 42
+'';       // 0
+'abc';    // NaN
'42' * 1;  // 42  : a multiplicação também força a conversão
'42' - 0;  // 42
'3' + '4'; // '34' : já a adição concatena!

O + colocado à frente de um valor aplica exatamente Number(). É curto, muito frequente no código existente e fácil de deixar passar na releitura: +valeur confunde-se com uma gralha. Num código partilhado, Number(valeur) diz o mesmo com mais clareza. E nunca uses a adição binária para converter: '3' + '4' dá a string '34'.

Tratar o NaN como deve ser

NaN (Not a Number) é o resultado de qualquer conversão falhada. Tem uma propriedade traiçoeira: não é igual a nada, nem sequer a si próprio.

javascript
const n = Number('abc');

n === NaN;          // false, sempre
Number.isNaN(n);    // true  : a forma correta de testar
isNaN('abc');       // true  : mas isNaN converte primeiro o argumento...
Number.isNaN('abc');// false : ... ao passo que Number.isNaN só deteta os NaN verdadeiros

O esquema habitual: converter, testar, aplicar um valor por omissão ou assinalar o erro.

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  (valor por omissão)
toNumber('', 10);  // 0  : a string vazia vale 0, não o valor por omissão

A última linha lembra a armadilha da string vazia: se um campo vazio tiver de ser tratado como «não preenchido», testa-o antes de converter.

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

O caso francês: a vírgula decimal

Nenhum dos quatro métodos percebe «12,5». Number devolve NaN, parseFloat para na vírgula e devolve 12, o que é pior: o programa segue com um valor errado. Normaliza o que foi escrito antes de converter.

parseFr.js
function parseFr(chaine) {
  const normalisee = String(chaine)
    .replace(/\s/g, '')   // retira os espaços dos milhares: «1 234,56»
    .replace(',', '.');   // vírgula decimal -> ponto
  return Number(normalisee);
}

parseFr('12,5');       // 12.5
parseFr('1 234,56');   // 1234.56
parseFr('12.5');       // 12.5 : o ponto continua a ser aceite

Num formulário, <input type="number"> evita o problema: o navegador mostra a vírgula ao utilizador francês mas transmite sempre um ponto em value.

Verificar se uma string é mesmo um número

Para saber se uma string representa um número antes de a usar, combina uma conversão estrita com Number.isFinite, que recusa NaN e 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

E para distinguir um inteiro de um decimal depois da conversão: Number.isInteger(42) vale true, Number.isInteger(3.99) vale false.

Os inteiros grandes: quando Number deixa de chegar

Number representa exatamente os inteiros até 253 − 1 (9 007 199 254 740 991). Acima disso, a precisão perde-se sem aviso: um identificador de base de dados em 64 bits ou um montante em cêntimos muito elevado podem ficar falseados.

javascript
Number('9007199254740993');   // 9007199254740992 : o último algarismo mudou
BigInt('9007199254740993');   // 9007199254740993n : exato
Number.MAX_SAFE_INTEGER;      // 9007199254740991

BigInt não se mistura com Number num cálculo e não aceita decimais; reserva-o para os identificadores e para os inteiros verdadeiramente grandes.

Que método escolher?

  • O valor tem de ser um número e mais nada (preço, quantidade, identificador): Number(), depois de pôr de lado a string vazia.
  • É preciso extrair um número de um texto («12.5px», «3 artigos»): parseFloat() para um decimal, parseInt(s, 10) para um inteiro.
  • O que foi escrito vem de um utilizador francês: normalizar a vírgula e os espaços, depois Number().
  • Estás a reler código com +valeur: isso é Number(valeur). Mantém-no se a equipa estiver habituada, mas nunca convertas com a adição '3' + '4'.
  • Em todos os casos: testa com Number.isNaN() ou Number.isFinite() antes de calcular.

A operação inversa, transformar um número numa string legível com duas casas decimais ou um separador de milhares, está tratada em Formatar um número em JavaScript. Para as bases da linguagem, o capítulo Variáveis e tipos de dados do tutorial explica porque é que uma string e um número são dois tipos distintos.

Erros frequentes

Esquecer a base do parseInt parseInt("08") vale 8 em todos os motores modernos, mas parseInt("0x1f") vale 31: a string é lida em hexadecimal. Passa sempre a base: parseInt(chaine, 10).
Contar com a vírgula decimal francesa Number("12,5") devolve NaN e parseFloat("12,5") devolve 12. Substitui a vírgula por um ponto antes da conversão.
Testar NaN com === NaN === NaN é falso. Usa Number.isNaN(valeur), nunca uma comparação direta.
Confundir a string vazia com zero Number("") e +"" valem 0, não NaN. Um campo de formulário deixado vazio torna-se assim um zero silencioso: testa chaine.trim() === "" antes de converter.

JavaScript

Damien Flandrin Programador web desde 2010, criador da Gekkode e do Email Impact. Cada artigo é testado num projeto real antes de ser publicado. Contacto
Newsletter

Os novos testes, tutoriais e projetos, por e-mail.

Testes reproduzíveis, código versionado, resultados datados. Nunca spam.