La clase `Number` en JavaScript

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 number primitivo y el objeto contenedor Number. 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_INTEGER pueden no representarse con precisión. Considere usar BigInt si se requiere precisión. EPSILON se 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() devuelve NaN a menos que toda la cadena sea estrictamente numérica, mientras que parseInt y parseFloat analizan la parte numérica legible desde el inicio de la cadena. Es más seguro especificar explícitamente la base al usar parseInt.

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.isNaN para 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.isSafeInteger para verificar y considere usar BigInt para 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)
  • toFixed devuelve 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.parseInt y Number.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 number y evite new Number().
  • Elija entre Number() (estricto) o parseInt/parseFloat (extracción parcial) para la conversión de cadenas a números dependiendo de su caso de uso.
  • Use Number.isNaN y Number.isFinite para comprobaciones seguras.
  • Para comparaciones de punto flotante, use Number.EPSILON o cree una función de comparación dedicada.
  • Cuando se requiera la precisión de los enteros, use Number.isSafeInteger y, si se supera el rango, use BigInt.
  • Puedes usar toFixed o toPrecision para 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.

YouTube Video