JavaScript convierte tipos automáticamente cuando lo necesita, un comportamiento llamado coerción implícita. Esto hace que operadores como == produzcan resultados que, sin conocer las reglas, parecen completamente arbitrarios. Entender cuándo ocurre esta conversión, y por qué === debe ser tu opción por defecto, es fundamental para escribir código correcto.
== aplica coerción, === no
El operador de igualdad débil == convierte los operandos al mismo tipo antes de comparar. El de igualdad estricta === compara valor y tipo sin conversión alguna:
// Igualdad débil con coerción
console.log(0 == false); // true (false ? 0)
console.log(1 == '1'); // true ('1' ? 1)
console.log('' == false); // true (ambos ? 0)
console.log(null == undefined); // true (caso especial)
// Igualdad estricta sin coerción
console.log(0 === false); // false (número vs booleano)
console.log(1 === '1'); // false (número vs string)
console.log(null === undefined); // false (tipos distintos)
Los casos que más confunden
Algunos resultados de == son especialmente contraintuitivos:
console.log([] == false); // true
console.log([] == 0); // true
console.log('' == 0); // true
console.log(' ' == 0); // true
// Pero:
console.log([] == ![]); // true (!)
// [] ? '' ? 0 y ![] ? false ? 0
console.log(null == 0); // false (null solo == undefined/null)
console.log(null == false); // false
// NaN no es igual a nada, ni a sí mismo
console.log(NaN == NaN); // false
console.log(NaN === NaN); // false
typeof para identificar tipos
typeof devuelve un string con el tipo del operando. Hay que conocer sus particularidades para no caer en errores:
typeof 42 // 'number'
typeof 'hola' // 'string'
typeof true // 'boolean'
typeof undefined // 'undefined'
typeof Symbol() // 'symbol'
typeof function(){}// 'function'
typeof {} // 'object'
typeof [] // 'object' (no 'array'!)
typeof null // 'object' (bug histórico de JS)
// Para detectar arrays:
Array.isArray([]) // true
// Para null:
let x = null;
x === null // true (la forma correcta)
Coerción en operaciones aritméticas
El operador + tiene un comportamiento especial: si alguno de los operandos es string, concatena en lugar de sumar. El resto de operadores aritméticos convierten a número:
1 + '2' // '12' (concatena) 1 - '2' // -1 (convierte '2' a número) '6' / '2' // 3 (ambos a número) true + 1 // 2 (true ? 1) false + 1 // 1 (false ? 0) null + 1 // 1 (null ? 0) undefined + 1 // NaN (undefined ? NaN) // El truco del + unario para convertir a número: +'42' // 42 +true // 1 +null // 0 +undefined // NaN +'' // 0
Cuándo usar == con criterio
Aunque la regla general es usar siempre ===, hay un caso donde == es idiomático y conveniente: comprobar si un valor es null o undefined a la vez:
// Comprueba null Y undefined con ==
function procesar(valor) {
if (valor == null) {
// entra si valor es null O undefined
return 'sin valor';
}
return valor;
}
// Equivalente más verboso con ===:
if (valor === null || valor === undefined) { ... }
// Hoy en día, el nullish coalescing ?? es más claro:
const resultado = valor ?? 'sin valor';
La recomendación práctica: configura un linter como ESLint con la regla eqeqeq para que avise siempre que uses == en lugar de ===. Así el código que use == será siempre una decisión consciente, no un olvido.
