Formatear precios en JavaScript con Intl.NumberFormat

Formatea precios en JavaScript con Intl.NumberFormat: moneda, idioma, decimales y validación del importe sin concatenaciones frágiles.

Formatear precios sin construirlos a mano

Formatear precios en JavaScript parece sencillo hasta que aparecen separadores de miles, monedas distintas o espacios que no coinciden entre idiomas. Intl.NumberFormat resuelve la presentación usando una configuración regional y un código de moneda. El dato sigue siendo un número. La representación resultante es texto preparado para mostrar al usuario, no una nueva cantidad con la que debas seguir calculando. Esta separación evita muchos errores en catálogos y resúmenes de compra.

Idioma y moneda son decisiones distintas

es-ES indica convenciones de presentación asociadas al español de España; EUR indica euros. Una tienda puede mostrar dólares a una persona que lee español, así que no deduzcas automáticamente la moneda del idioma. Define ambos valores según el contexto comercial. Para probar otra combinación cambia el identificador regional y el código de moneda. La posición del símbolo, los separadores y los decimales pueden variar sin que tengas que mantener una colección de reemplazos manuales.

Código completo para probar en tu navegador

Copia este documento en un archivo index.html, guarda los cambios y ábrelo en el navegador. El ejemplo no requiere bibliotecas.

<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Formatear precios en JavaScript con Intl.NumberFormat</title>
<style>
*{box-sizing:border-box}body{font:16px/1.6 system-ui,sans-serif;max-width:900px;margin:2rem auto;padding:1rem;color:#17233b}label{display:block;font-weight:700;margin-top:1rem}input,textarea,select,button{font:inherit;padding:.65rem;max-width:100%}textarea{width:100%}button{cursor:pointer}button:focus-visible,a:focus-visible{outline:3px solid #173b94;outline-offset:3px}[hidden]{display:none!important}[role=tab][aria-selected=true]{background:#173b94;color:white}[role=tab]{border:1px solid #bdcbe2;border-radius:.5rem}[role=tabpanel]{padding:1rem;border:1px solid #bdcbe2}
</style>
</head>
<body>
<label for="importe">Importe en euros</label>
<input id="importe" type="number" step="0.01" value="1299.5">
<button id="calcular" type="button">Formatear precio</button>
<p id="salida" role="status"></p>
<script>
const campo=document.querySelector('#importe');
const salida=document.querySelector('#salida');
const formato=new Intl.NumberFormat('es-ES',{style:'currency',currency:'EUR'});
document.querySelector('#calcular').addEventListener('click',()=>{
 const valor=campo.valueAsNumber;
 salida.textContent=campo.value!=='' && Number.isFinite(valor)
  ? formato.format(valor) : 'Introduce un importe válido.';
});
</script>
</body>
</html>

Leer un campo numérico

El input de tipo number expone valueAsNumber. Un campo vacío no representa cero: el ejemplo comprueba además que exista un valor antes de formatear. Number.isFinite rechaza resultados no válidos. Si tu negocio admite solamente cantidades positivas, añade min y verifica esa condición también en la lógica de envío. El snippet permite negativos deliberadamente, porque pueden representar descuentos, saldos o devoluciones. La regla correcta depende del significado del importe, no del aspecto del control.

Mostrar no equivale a calcular

El formato de moneda no corrige por sí solo los problemas de precisión de la aritmética de coma flotante. Una factura con impuestos y descuentos necesita reglas de redondeo definidas antes de presentar el total. En sistemas sencillos puedes trabajar con unidades menores enteras cuando la moneda y el dominio lo permiten. En procesos financieros más complejos conviene una estrategia decimal adecuada. Evita usar el texto formateado como fuente de verdad para reconstruir el importe.

Decimales y expectativas

Las monedas no comparten necesariamente el mismo número habitual de decimales. Intl aplica valores por defecto relacionados con la moneda elegida. Si fuerzas minimumFractionDigits y maximumFractionDigits, documenta por qué lo haces y comprueba el resultado con esa moneda. No ocultes céntimos en un precio final si eso cambia lo que el cliente entiende que pagará. Un panel resumido puede abreviar cifras, pero el detalle de una operación debe mostrar el importe con precisión suficiente.

No analizar una cadena localizada con parseFloat

Una cadena como 1.299,50 no tiene el mismo significado para parseFloat que para una persona acostumbrada a la notación española. El parser puede detenerse antes de lo que esperas y producir una cantidad incorrecta sin lanzar un error evidente. Usa un campo numérico o recibe datos estructurados de tu API. Si necesitas aceptar entrada localizada libre, diseña y prueba una conversión específica; eliminar comas y puntos sin contexto no es una solución universal.

Reutilizar el formateador

El ejemplo crea una instancia y la utiliza cada vez que se pulsa el botón. En una tabla con muchas filas puedes compartir ese mismo objeto mientras la configuración sea idéntica. Si el usuario cambia la moneda, crea el formateador correspondiente y conserva los importes originales. Cambiar EUR por USD solamente cambia la etiqueta y la presentación; no aplica un tipo de cambio. Una conversión real necesita una tasa, una fecha y reglas que la aplicación pueda explicar.

Pruebas con valores que descubren errores

Prueba cero, una cantidad negativa, un campo vacío, un importe con céntimos y otro de varios millones. Revisa también una moneda con convenciones diferentes. No compares la salida con una cadena escrita a mano en la que todos los espacios sean ordinarios: el formato puede incluir espacios especiales. Para mostrar el resultado usa textContent, como hace el snippet. Si necesitas personalizar partes del precio, formatToParts permite identificarlas sin dividir la cadena mediante posiciones frágiles.

Elegir entre símbolo y código de moneda

El símbolo puede ser ambiguo cuando varias monedas lo comparten. Si una aplicación trabaja con distintos mercados, considera currencyDisplay code o una etiqueta de moneda visible cerca del importe. No cambies esta opción solamente por estética: la persona debe entender qué cantidad está viendo y en qué unidad. Para una tabla que mezcla monedas, define un criterio consistente en todas las filas. También puedes separar el dato monetario del resto de la descripción para facilitar su lectura, manteniendo siempre el código original en tu modelo de datos y sin reconstruirlo desde el texto mostrado.

Importes que llegan desde una API

Comprueba el contrato de la respuesta antes de formatear. Un servicio puede entregar una cantidad numérica, una cadena decimal o un entero en unidades menores. No dividas siempre entre cien por costumbre: debes conocer la unidad y la moneda que usa esa API. Valida el dato y comunica un estado de error cuando falte, en lugar de mostrar cero como sustituto silencioso. Un precio ausente no significa gratuito. Para un catálogo, un mensaje como Precio no disponible puede ser más correcto que presentar una cantidad que el negocio nunca proporcionó.

Separar las pruebas de presentación y negocio

Puedes comprobar que el formateador produce una salida legible para distintas configuraciones sin mezclarlo con impuestos, descuentos o conversión. Después prueba esas reglas comerciales con sus propios casos. Incluye cantidades límite que tengan sentido para tu producto y confirma qué política se aplica al redondear. Si cada pantalla calcula el total de una forma distinta, Intl no resolverá la discrepancia. Mantén una fuente de verdad para el importe y utiliza el formato solamente al presentarlo. Esa separación facilita modificar el diseño sin introducir cambios accidentales en lo que se cobra.

Una interfaz que no inventa importes

Cuando el dato todavía no llega, muestra un estado de espera o una ausencia explicada. No uses cero como precio provisional si el usuario puede interpretarlo como una oferta. Tampoco conserves un importe anterior después de que falle una actualización sin indicar su estado. El ejemplo local evita estas situaciones porque la entrada es inmediata, pero un catálogo real necesita tratarlas. Revisa el recorrido de carga y error con la misma atención que el formato correcto. La legibilidad de la moneda sirve de poco si la cantidad presentada no corresponde al producto actual.

Guías relacionadas para seguir practicando

Puedes ampliar esta práctica con Declarar variables en JavaScript y Trabajar con datos JSON.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

logo mastercode pro
Resumen de privacidad

Esta web utiliza cookies para que podamos ofrecerte la mejor experiencia de usuario posible. La información de las cookies se almacena en tu navegador y realiza funciones tales como reconocerte cuando vuelves a nuestra web o ayudar a nuestro equipo a comprender qué secciones de la web encuentras más interesantes y útiles.

Puedes ver mas detalle en nuestra pagina de privcidad