A classe `Number` em JavaScript

A classe `Number` em JavaScript

Este artigo explica a classe Number em JavaScript.

Explicaremos cuidadosamente as características de Number, armadilhas comuns, APIs úteis e exemplos práticos passo a passo.

YouTube Video

A classe Number em JavaScript

Number é o tipo numérico fundamental em JavaScript e é representado como um ponto flutuante de dupla precisão IEEE-754 (64 bits).

Noções básicas: Representação dos números e verificação de tipo

Em JavaScript, todos os números são representados como o tipo primitivo number.

 1// Primitive numbers and Number object
 2const a = 42;                 // primitive number
 3const b = 3.14;               // primitive float
 4const c = Number(10);         // primitive via constructor call (function form)
 5const d = new Number(10);     // Number object (wrapper)
 6
 7console.log(typeof a);        // "number"
 8console.log(typeof d);        // "object"
 9console.log(c == d);          // true  (value coerces)
10console.log(c === d);         // false (different types)
  • Este código demonstra a diferença entre um number primitivo e o objeto wrapper Number. Normalmente, usam-se primitivos em vez de wrappers.

Valores especiais: NaN, Infinity e constantes

Number fornece valores especiais (NaN, Infinity) e constantes.

 1// Special numeric values and constants
 2console.log(Number.NaN);                 // NaN
 3console.log(Number.POSITIVE_INFINITY);   // Infinity
 4console.log(Number.NEGATIVE_INFINITY);   // -Infinity
 5
 6console.log(Number.MAX_VALUE);           // largest positive representable
 7console.log(Number.MIN_VALUE);           // smallest positive representable (closest to 0)
 8console.log(Number.MAX_SAFE_INTEGER);    // 9007199254740991
 9console.log(Number.MIN_SAFE_INTEGER);    // -9007199254740991
10console.log(Number.EPSILON);             // smallest difference ~2.220446049250313e-16
  • Números inteiros maiores ou iguais a MAX_SAFE_INTEGER podem não ser representados com precisão. Considere usar BigInt caso seja necessário garantir a precisão. EPSILON é utilizado para comparações de números de ponto flutuante.

Conversão de números: Number(), parseInt, parseFloat e o operador +

Existem diversas maneiras de converter uma string para número, cada uma com diferentes comportamentos.

 1// Converting strings to numbers
 2console.log(Number("42"));        // 42
 3console.log(Number("  3.14 "));   // 3.14
 4console.log(+ "7");               // 7 (unary +)
 5
 6console.log(parseInt("42px"));    // 42
 7console.log(parseFloat("3.14abc"));// 3.14
 8
 9// Careful with parseInt and radix
10console.log(parseInt("08"));      // 8
11console.log(parseInt("08", 10));  // 8 (explicit radix is safer)
  • Number() retorna NaN a menos que toda a string esteja estritamente em formato numérico, enquanto parseInt e parseFloat extraem a parte numérica legível a partir do início da string. É mais seguro sempre especificar explicitamente a base numérica (radix) ao usar parseInt.

Tratamento e verificação de NaN: isNaN e Number.isNaN

NaN (Not-A-Number) é especial porque NaN !== NaN. Há diferenças na forma de verificação; o método global isNaN faz conversão de tipos e pode gerar falsos positivos, por isso recomenda-se usar Number.isNaN.

1// NaN detection differences
2console.log(NaN === NaN);             // false
3
4console.log(isNaN("foo"));            // true  -> because "foo" coerces to NaN
5console.log(Number.isNaN("foo"));     // false -> "foo" is not the numeric NaN
6
7console.log(Number.isNaN(NaN));       // true
  • Use Number.isNaN para verificação de números e validação de resultados de cálculos para evitar conversão de tipos desnecessária.

Erros de ponto flutuante e comparações usando Number.EPSILON

Devido à norma IEEE-754, ocorrem erros como 0.1 + 0.2 !== 0.3. Para comparações estritas, é comum usar a diferença e Number.EPSILON.

1// Floating point precision example and EPSILON comparison
2const sum = 0.1 + 0.2;
3console.log(sum === 0.3);             // false
4
5function nearlyEqual(a, b, epsilon = Number.EPSILON) {
6  return Math.abs(a - b) <= epsilon * Math.max(1, Math.abs(a), Math.abs(b));
7}
8
9console.log(nearlyEqual(sum, 0.3));   // true
  • Ao tolerar erros em comparações, recomenda-se uma implementação robusta como nearlyEqual, que também leva em conta o escalonamento e utiliza a diferença absoluta.

Verificação de inteiros e inteiros seguros (isInteger, isSafeInteger)

Existem APIs para verificar se um valor é um inteiro e se está dentro da faixa de inteiros seguros.

1// Integer and safe integer checks
2console.log(Number.isInteger(3));                 // true
3console.log(Number.isInteger(3.0));               // true
4console.log(Number.isInteger(3.1));               // false
5
6console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER)); // true
7console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1)); // false
  • Quando a precisão de grandes inteiros for necessária, use Number.isSafeInteger para verificar, e considere usar BigInt para números que excedam esse intervalo.

Exibição e formatação: toFixed, toPrecision, toString

Existem métodos disponíveis para controlar a exibição dos números. toFixed retorna uma string com um número especificado de casas decimais, mas é preciso atenção com o arredondamento.

1// Formatting numbers for display
2const x = 1.23456;
3console.log(x.toFixed(2));         // "1.23"   (string)
4console.log(x.toPrecision(3));     // "1.23"   (string with total significant digits)
5console.log((255).toString(16));   // "ff"     (hexadecimal string)
  • toFixed retorna uma string, então é importante estar ciente dos valores ao convertê-los novamente para número para cálculos.

Cuidados sobre concatenação de strings e o operador +

O operador + é usado tanto para soma numérica quanto para concatenação de strings, portanto, podem ocorrer resultados inesperados dependendo dos tipos de dados envolvidos.

1// Pitfall with + operator and type coercion
2console.log(1 + 2 + "px");    // "3px"
3console.log("px" + 1 + 2);    // "px12"
4console.log(1 + "2" - 0);     // 3  (string coerced to number for subtraction)
  • Ao misturar strings e números, é mais seguro usar explicitamente String(), Number() ou literais template para evitar conversão implícita de tipos.

Casos avançados: Number.parseInt / Number.parseFloat, valueOf

Number.parseInt e Number.parseFloat são aliases das funções globais. valueOf é utilizado para recuperar o valor primitivo de um objeto Number, mas raramente é necessário na prática.

1// Number.parseInt/parseFloat aliases and valueOf example
2console.log(Number.parseInt("100", 10));   // 100
3console.log(Number.parseFloat("3.14"));    // 3.14
4
5const nObj = new Number(5);
6console.log(nObj.valueOf());               // 5
7console.log(nObj + 1);                     // 6  (object coerced to primitive)
  • Ao usar Number.parseInt e Number.parseFloat, tenha atenção com a base numérica (radix) e a limpeza do input. Objetos wrapper geralmente são evitados.

Referência: Pequeno exemplo utilitário - Funções de validação de números

Aqui estão pequenas funções utilitárias que reúnem verificações comumente usadas. Isso torna tarefas como validação de entrada mais fáceis.

 1// Small number utility functions
 2function toNumberStrict(value) {
 3  // Return a Number or throw for invalid numeric strings
 4  const n = Number(value);
 5  if (typeof value === "string" && value.trim() === "") {
 6    throw new Error("Empty string is not a valid number");
 7  }
 8  if (Number.isNaN(n)) {
 9    throw new Error(`Invalid number: ${value}`);
10  }
11  return n;
12}
13
14function almostEqual(a, b, eps = Number.EPSILON) {
15  // Robust relative comparison
16  return Math.abs(a - b) <= eps * Math.max(1, Math.abs(a), Math.abs(b));
17}
  • São funções de alta versatilidade que podem ser usadas repetidamente para processamento e comparação de entradas. Implementações que geram erros são úteis para fins de validação.

Resumo sobre desempenho e boas práticas

A seguir estão pontos práticos ao usar Number.

  • Basicamente, use o tipo primitivo number e evite new Number().
  • Escolha entre Number() (estrito) ou parseInt/parseFloat (extração parcial) para conversão de string para número, dependendo do seu caso de uso.
  • Use Number.isNaN e Number.isFinite para verificações seguras.
  • Para comparações de ponto flutuante, use Number.EPSILON ou crie uma função de comparação dedicada.
  • Quando a precisão de inteiros for necessária, use Number.isSafeInteger e, se exceder o intervalo, use BigInt.
  • Você pode usar toFixed ou toPrecision para arredondar para exibição, mas note que o valor retornado é uma string.

Resumo

Number é o tipo básico para todos os números em JavaScript, incluindo inteiros, decimais e valores especiais (NaN e Infinity). É importante estar ciente da conversão de tipos e dos erros de ponto flutuante, e utilizar corretamente métodos como Number.isNaN e Number.EPSILON. Se o limite de inteiros seguros for excedido, use BigInt, e use toFixed ou toPrecision para arredondamento e exibição.

Você pode acompanhar o artigo acima usando o Visual Studio Code em nosso canal do YouTube. Por favor, confira também o canal do YouTube.

YouTube Video