La clase `Number` en JavaScript
Este artículo explica la clase Number en JavaScript.
Explicaremos cuidadosamente las características de Number, errores comunes, APIs útiles y ejemplos prácticos paso a paso.
YouTube Video
La clase Number en JavaScript
Number es el tipo numérico fundamental en JavaScript y se representa como un punto flotante de doble precisión IEEE-754 (64 bits).
Conceptos básicos: representación de números y comprobación de tipos
En JavaScript, todos los números se representan como el 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 muestra la diferencia entre un
numberprimitivo y el objeto contenedorNumber. Normalmente se usan los primitivos en lugar de los objetos envoltorios.
Valores especiales: NaN, Infinity y constantes
Number ofrece valores especiales (NaN, Infinity) y 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
- Los enteros mayores o iguales a
MAX_SAFE_INTEGERpueden no representarse con precisión. Considere usarBigIntsi se requiere precisión.EPSILONse utiliza para comparaciones de punto flotante.
Conversión de números: Number(), parseInt, parseFloat y el operador +
Hay varias formas de convertir una cadena en un número, cada una con comportamientos diferentes.
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()devuelveNaNa menos que toda la cadena sea estrictamente numérica, mientras queparseIntyparseFloatanalizan la parte numérica legible desde el inicio de la cadena. Es más seguro especificar explícitamente la base al usarparseInt.
Manejo y comprobación de NaN: isNaN y Number.isNaN
NaN (Not-A-Number) es especial porque NaN !== NaN. Hay diferencias en cómo verifican; el global isNaN realiza conversión de tipos y puede dar falsos positivos, por lo que se recomienda 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 verificar números y validar resultados de cálculos para evitar conversiones de tipo innecesarias.
Errores de punto flotante y comparaciones usando Number.EPSILON
Debido a IEEE-754, ocurren errores como 0.1 + 0.2 !== 0.3. Para comparaciones estrictas, es común usar la diferencia y 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
- Cuando se permiten márgenes de error en la comparación, se recomienda una implementación robusta como
nearlyEqual, que también considera el escalado y las diferencias absolutas.
Verificación de enteros y enteros seguros (isInteger, isSafeInteger)
Existen APIs para verificar si un valor es un entero y si está dentro del rango seguro de enteros.
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
- Cuando sea necesaria la precisión de enteros grandes, use
Number.isSafeIntegerpara verificar y considere usarBigIntpara números que superan ese rango.
Visualización y formato: toFixed, toPrecision, toString
Existen métodos para controlar la visualización de los números. toFixed devuelve una cadena con un número especificado de decimales, pero se debe tener cuidado con el redondeo.
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)
toFixeddevuelve una cadena, así que tenga cuidado con los valores al convertirlos nuevamente en números para cálculos.
Precauciones sobre la concatenación de cadenas y el operador +
El operador + se utiliza tanto para la suma numérica como para la concatenación de cadenas, por lo que pueden ocurrir resultados inesperados según los tipos de datos involucrados.
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)
- Cuando se mezclan cadenas y números, es más seguro usar explícitamente
String(),Number()o literales de plantilla para evitar conversiones implícitas de tipo.
Casos de uso avanzados: Number.parseInt / Number.parseFloat, valueOf
Number.parseInt y Number.parseFloat son alias de las funciones globales. valueOf se utiliza para obtener el valor primitivo de un objeto Number, pero rara vez es necesario en la práctica.
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)
- Al usar
Number.parseIntyNumber.parseFloat, tenga cuidado con la base y el recorte del valor de entrada. Generalmente se evitan los objetos envoltorios.
Referencia: pequeño ejemplo de utilidad: funciones de validación de números
Aquí hay pequeñas funciones de utilidad que recogen comprobaciones habituales. Esto facilita tareas como la validación de entradas.
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}- Son funciones muy versátiles que pueden reutilizarse para el procesamiento y la comparación de entradas. Las implementaciones que lanzan errores son útiles para la validación.
Resumen de rendimiento y mejores prácticas
A continuación se presentan puntos prácticos al usar Number.
- Básicamente, use el tipo primitivo
numbery evitenew Number(). - Elija entre
Number()(estricto) oparseInt/parseFloat(extracción parcial) para la conversión de cadenas a números dependiendo de su caso de uso. - Use
Number.isNaNyNumber.isFinitepara comprobaciones seguras. - Para comparaciones de punto flotante, use
Number.EPSILONo cree una función de comparación dedicada. - Cuando se requiera la precisión de los enteros, use
Number.isSafeIntegery, si se supera el rango, useBigInt. - Puedes usar
toFixedotoPrecisionpara redondear para mostrar, pero ten en cuenta que el valor retornado es una cadena.
Resumen
Number es el tipo básico para todos los números en JavaScript, incluidos enteros, decimales y valores especiales (NaN e Infinity). Es importante ser consciente de la conversión de tipos y los errores de punto flotante, y utilizar correctamente métodos como Number.isNaN y Number.EPSILON. Si se supera el rango de enteros seguros, utilice BigInt y utilice toFixed o toPrecision para redondear y mostrar.
Puedes seguir el artículo anterior utilizando Visual Studio Code en nuestro canal de YouTube. Por favor, también revisa nuestro canal de YouTube.