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
numberprimitivo e o objeto wrapperNumber. 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_INTEGERpodem não ser representados com precisão. Considere usarBigIntcaso 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()retornaNaNa menos que toda a string esteja estritamente em formato numérico, enquantoparseInteparseFloatextraem a parte numérica legível a partir do início da string. É mais seguro sempre especificar explicitamente a base numérica (radix) ao usarparseInt.
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.isNaNpara 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.isSafeIntegerpara verificar, e considere usarBigIntpara 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)
toFixedretorna 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.parseInteNumber.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
numbere evitenew Number(). - Escolha entre
Number()(estrito) ouparseInt/parseFloat(extração parcial) para conversão de string para número, dependendo do seu caso de uso. - Use
Number.isNaNeNumber.isFinitepara verificações seguras. - Para comparações de ponto flutuante, use
Number.EPSILONou crie uma função de comparação dedicada. - Quando a precisão de inteiros for necessária, use
Number.isSafeIntegere, se exceder o intervalo, useBigInt. - Você pode usar
toFixedoutoPrecisionpara 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.