
En resumen
console.log imprime una referencia viva al objeto, por eso el estado registrado parece cambiar después. table, group, time y assert convierten ese ruido en evidencia estructurada.
Casi toda depuración empieza con console.log y termina ahí, lo cual es una lástima: la consola tiene una docena de métodos y la diferencia entre ellos es la diferencia entre leer un muro de texto y leer una respuesta. Esta guía cubre los métodos que merece la pena conocer, el comportamiento de referencia frente a copia que hace que los logs parezcan incorrectos y cómo leer un stack trace cuando una llamada asíncrona falla en silencio.
Todo esto se ejecuta en el ejecutor de JavaScript de UrsaKit, que imprime la salida de consola con niveles, agrupación y tiempo de ejecución.
01console.log es solo la primera herramienta
console.log escribe lo que le das, en orden, sin estructura. Está bien para un número y es inútil para una lista de cuarenta registros. El resto de la API existe para añadir estructura:
| Método | Úsalo para |
|---|---|
console.log | Cualquier valor; formateado con %s / %d / %o |
console.table | Arrays de objetos, renderizados como tabla |
console.dir | Inspeccionar las propiedades de un objeto en lugar de su toString |
console.group / console.groupEnd | Anidar salida relacionada |
console.time / console.timeEnd | Medir el tiempo entre dos puntos |
console.count | Contar cuántas veces se ejecuta una rama |
console.assert | Escribir solo cuando falla una suposición |
console.trace | Imprimir un stack trace en el punto actual |
02Los objetos se registran por referencia
Este es el comportamiento que más tiempo hace perder, porque la consola no miente: muestra el objeto vivo.
const user = { name: 'Ada', plan: 'free' }
console.log(user) // al expandirlo puede mostrar { name: 'Grace', plan: 'pro' }
console.log(user.name) // 'Ada' — un primitivo se captura por valor
user.name = 'Grace'
user.plan = 'pro'
En una consola interactiva la vista del objeto se construye al expandirla, así que refleja el estado final del objeto, no el momento de la llamada. Tres formas de capturar el valor:
console.log(user.name) // registra el primitivo que te importa
console.log(JSON.stringify(user)) // una instantánea en cadena, legible en cualquier consola
console.log(structuredClone(user)) // una copia profunda real, conserva los tipos
Registra el estado que estás comparando, no el objeto entero.
console.log('plan=' + user.plan + ' items=' + items.length)sobrevive a la serialización, se lee igual en un log de servidor y en el navegador, y no puede cambiar por debajo. Reserva el volcado completo para la exploración.
03Agrupar y medir tiempos
La salida relacionada se vuelve legible cuando está anidada, y las duraciones se vuelven comparables cuando se miden en lugar de estimarse.
console.group('checkout')
console.time('validate')
console.count('line') // line: 1
console.count('line') // line: 2
for (let i = 0; i < 1e6; i++) {
/* work */
}
console.timeEnd('validate') // validate: 12.4ms
console.groupEnd()
Algunos detalles que importan en la práctica:
console.timeyconsole.timeEnddeben usar la misma etiqueta, y cada etiqueta debe cerrarse antes de poder abrirse de nuevo.console.countempieza cada etiqueta en cero e imprime el total acumulado, la forma más rápida de demostrar que una función de render se ejecuta dos veces.console.groupCollapsedes igual queconsole.grouppero empieza cerrado, lo que mantiene legible una ejecución larga.
El tiempo medido así incluye todo lo que hay entre las dos llamadas, así que sirve para comparaciones relativas —antes y después de un cambio— más que como benchmark. El ejecutor también informa del tiempo total del fragmento.
04Aserciones y conteo
console.assert es lo contrario de console.log: se queda callado mientras tu suposición se cumple.
function applyDiscount(price, percent) {
console.assert(
percent >= 0 && percent <= 100,
'discount out of range',
percent
)
return price * (1 - percent / 100)
}
applyDiscount(100, 20) // sin salida
applyDiscount(100, 150) // Assertion failed: discount out of range 150
Dentro de un bucle, una aserción es un filtro: solo obtienes salida para los registros que rompen la regla, en lugar de desplazarte por los que no.
05Leer un stack trace
Cuando necesitas saber qué llamante llegó a una función, imprime un trace en lugar de añadir un log a cada candidato:
function parse(input) {
console.trace('parse called')
return JSON.parse(input)
}
parse('{"a":1}')
// parse called
// at parse (<anonymous>:2:11)
// at <anonymous>:4:1
Para errores lanzados, la pila es el mapa desde el fallo hasta el punto de llamada. Léela de arriba abajo: la primera línea es donde se lanzó el error y las siguientes son sus llamantes. El marco que pertenece a tu código —no a una biblioteca ni al runtime— suele ser el que hay que arreglar.
try {
JSON.parse('{ "a": 1, }')
} catch (error) {
console.error(error.name) // SyntaxError
console.error(error.message) // Expected double-quoted property name in JSON at position 9
console.error(error.stack) // dónde ocurrió, marco a marco
}
06Errores asíncronos que nunca llegan a un log
Un error lanzado dentro de una función asíncrona se convierte en una promesa rechazada. Si nadie la maneja, el fallo puede ocurrir sin pasar nunca por la línea que estabas mirando.
async function load() {
throw new Error('network down')
}
load() // rechazo sin manejar: nada lo captura
Dos hábitos hacen visibles estos fallos:
- Usa await dentro de try/catch, para que el fallo caiga en una línea que controlas.
- Maneja los rechazos en el límite con
.catch()en llamadas sin espera, o escuchando el evento de rechazo del runtime en una página propia.
async function load() {
throw new Error('network down')
}
try {
await load()
} catch (error) {
console.error('load failed:', error.message) // load failed: network down
}
No publiques salida de consola verbosa.
Los logs de depuración en producción filtran estado interno a cualquiera que abra la consola, y registrar objetos grandes en una ruta caliente cuesta tiempo real. Ponlos detrás de un flag o elimínalos antes de compilar.
07Practicar en un entorno aislado
- Pega un fragmento y ejecútalo — El ejecutor de JavaScript analiza el código primero e informa de los errores de sintaxis con número de línea.
- Lee la salida por niveles — Las líneas de log, warn y error se distinguen, y la consola agrupa la salida igual que el navegador.
- Mira el temporizador — La duración informada es el coste real del fragmento, suficiente para comparar dos enfoques.
- Prueba la rama que falla — Vuelve a ejecutar con una entrada que rompa la suposición, porque la aserción que nunca disparaste es la que habría cazado el bug.
La consola es una herramienta de medición, no un bloc de notas. Usar el método correcto es lo que convierte una página de salida en una sola línea que responde a la pregunta.
Ejecuta fragmentos en una consola aislada con comprobación de sintaxis, tiempo de ejecución y salida por niveles.
Ejecutor de JavaScriptPreguntas frecuentes
¿Por qué console.log muestra un valor incorrecto para mi objeto?
La consola guarda una referencia viva al objeto, no una copia. Si el objeto se modifica después, la vista expandida muestra el estado actual. Registra un primitivo, una cadena JSON o un structuredClone para capturar el valor de ese momento.
¿Qué hace exactamente console.table?
Renderiza un array de objetos como tabla, usando las claves como columnas. Es la forma más rápida de leer una lista de registros y acepta un segundo argumento para limitar las columnas.
¿Cuándo debería usar console.assert?
Cuando solo quieres salida si se incumple una suposición. console.assert(condición, mensaje) no escribe nada mientras la condición sea verdadera, lo que mantiene la consola limpia.
¿Es igual console en Node.js y en el navegador?
En gran medida. table, group, time, count y assert existen en ambos, pero el navegador renderiza objetos interactivos y Node imprime el resultado de inspect, además de eventos de proceso como unhandledRejection.
¿Las llamadas a console ralentizan producción?
Registrar objetos grandes tiene coste, y dejar logs verbosos en producción filtra datos internos a cualquiera que abra la consola. Elimínalos o ponlos detrás de un flag antes de publicar.
¿Cómo veo un stack trace sin lanzar un error?
Llama a console.trace(). Imprime un stack trace en el punto de la llamada, que es justo como descubres cuál de cinco llamantes tiene la culpa.
Artículos relacionados
- Cómo formatear, validar y minificar JSON
Convierte el objeto inspeccionado en algo legible y comparable.
- Grupos, lookarounds y backtracking en regex
Prueba en la consola el patrón que estás depurando con cadenas reales.
Herramientas relacionadas
- Ejecutor de JavaScript
Consola aislada con tiempos y salida por niveles.
- Formateador y validador JSON
Formatea el objeto que volcaste.
- Herramienta HTML Online
Renderiza el marcado que produce tu script.
- Probador de expresiones regulares
Comprueba el patrón del que depende tu código.