10 Curiosidades sobre JavaScript y su comportamiento
JavaScript es un lenguaje lleno de curiosidades 🤯.
Algunas son parte de su diseño original, otras nacen de su evolución y compatibilidad con versiones antiguas.
Si alguna vez viste algo que “no tiene sentido” en JavaScript… probablemente tiene una explicación (aunque no siempre lógica).
1. NaN significa “Not a Number”… pero es un número 😵💫
Sí, es real. El valor NaN (Not a Number) es de tipo number.
typeof NaN; // 'number'
Esto ocurre porque NaN representa el resultado de una operación matemática inválida dentro del conjunto de los números, pero JavaScript lo clasifica igual como number.
| Expresión | Resultado |
|---|---|
0 / 0 | NaN |
Math.sqrt(-1) | NaN |
parseInt("Hola") | NaN |
🔹 Dato curioso: NaN no es igual a sí mismo.
NaN === NaN; // false
Si quieres comprobar si algo es NaN, debes usar Number.isNaN().
2. == vs ===: el caos de la coerción ⚖️
El doble igual (==) realiza coerción de tipos automática, tratando de convertir los valores para compararlos.
Mientras que el triple igual (===) no hace conversiones y compara directamente el tipo y el valor.
0 == '0'; // true
0 === '0'; // false
false == 0; // true
false === 0; // false
null == undefined; // true
null === undefined; // false
📌 Regla de oro: usa siempre === para evitar resultados inesperados.
3. Los arrays son… objetos disfrazados 🧊
typeof [] === 'object'; // true
En realidad, los arrays son objetos con propiedades numéricas y un prototipo especial.
Por eso, puedes hacer cosas como:
const arr = [1, 2, 3];
arr.nombre = "Mi arreglo";
console.log(arr.nombre); // "Mi arreglo"
console.log(arr.length); // 3
Solo las claves numéricas afectan la propiedad length.
Las propiedades adicionales son tratadas como atributos normales de objeto.
4. [] + [] y otros resultados absurdos 🧩
A veces, los operadores en JavaScript no hacen lo que crees.
[] + []; // ''
[] + {}; // '[object Object]'
{} + []; // 0
{} + {}; // '[object Object][object Object]'
Esto ocurre por coerción implícita al convertir los valores a string o number según el contexto.
👉 Cuando se usa + con objetos, el motor intenta convertirlos en primitivos.
Los arrays se convierten en cadenas vacías (""), y los objetos en "[object Object]".
5. typeof null retorna 'object' 🔄
Uno de los errores más antiguos (¡y aún vigente!) del lenguaje.
typeof null; // 'object'
Esto es un bug heredado de las primeras versiones de JavaScript (1995).
Internamente, los valores se representaban con bits, y el identificador para object era 0.
Como null también usaba ese bit pattern, el resultado quedó… para siempre.
Brendan Eich (creador de JS) decidió mantenerlo por compatibilidad histórica.
6. setTimeout(..., 0) no se ejecuta de inmediato 🕰️
Aunque pongas el delay en 0, JavaScript nunca interrumpe la pila actual de ejecución.
El callback se agenda para después de que la pila esté vacía.
console.log("Inicio");
setTimeout(() => console.log("Timeout"), 0);
console.log("Fin");
Salida:
Inicio
Fin
Timeout
💡 Explicación:
El motor JS usa una cola de tareas (Event Loop).
El callback de setTimeout se ejecuta después del bloque sincrónico actual.
7. Variables “flotantes” por hoisting 🧠
El hoisting hace que las declaraciones (no asignaciones) se “eleven” al principio del scope.
console.log(a); // undefined
var a = 10;
Esto equivale a:
var a;
console.log(a);
a = 10;
Pero con let y const, no ocurre hoisting accesible:
console.log(b); // ❌ ReferenceError
let b = 20;
📎 Diferencias clave:
| Tipo | Hoisting | Inicialización | Reasignable |
|---|---|---|---|
var | Sí | undefined | ✅ |
let | Sí (zona muerta temporal) | ❌ | ✅ |
const | Sí (zona muerta temporal) | ❌ | ❌ |
8. El número máximo seguro en JavaScript 💯
Los números en JS siguen el estándar IEEE 754, lo que significa que pueden perder precisión.
Number.MAX_SAFE_INTEGER; // 9007199254740991
Si lo superas, empiezan los errores:
9007199254740991 + 1; // 9007199254740992
9007199254740991 + 2; // 9007199254740992 ❌
Para valores grandes, usa BigInt:
const big = 9007199254740991n + 2n;
console.log(big); // 9007199254740993n
9. this cambia según el contexto 🎭
El valor de this no se define por dónde se declara una función, sino por cómo se llama.
const persona = {
nombre: "Felipe",
saludar() {
console.log(`Hola, soy ${this.nombre}`);
}
};
const saludar = persona.saludar;
persona.saludar(); // Hola, soy Felipe
saludar(); // Hola, soy undefined
💡 En el segundo caso, this apunta al objeto global, no al objeto original.
Por eso, si usas funciones callback, a menudo conviene usarlas con arrow functions o bind().
10. El misterio de 0.1 + 0.2 🧨
Un clásico de los errores de precisión flotante:
0.1 + 0.2 === 0.3; // false
El resultado es 0.30000000000000004.
Esto pasa porque los números binarios no pueden representar con exactitud algunos decimales.
✅ Solución práctica:
Number((0.1 + 0.2).toFixed(2)) === 0.3; // true
💡 Reflexión final
JavaScript puede parecer incoherente, pero muchas de sus rarezas provienen de decisiones históricas y de su flexibilidad como lenguaje dinámico.
Entender estas curiosidades no solo evita errores: también te convierte en un desarrollador más consciente de cómo piensa realmente el motor de JS 🔥.