Operadores en JavaScript: == vs ===, &&, || y ??
Actualizado el 29 de septiembre de 2026
Los operadores de JavaScript se parecen a los de cualquier otro lenguaje, con dos diferencias que causan muchos errores: existen dos formas de comparar igualdad (== y ===), y los operadores lógicos no devuelven true o false, sino uno de sus operandos.
En esta guía vas a ver los operadores aritméticos, de comparación y lógicos, el operador ?? para valores por defecto y las reglas que conviene seguir para no tropezar con las conversiones automáticas.
Operadores aritméticos
7 + 2 // 9
7 - 2 // 5
7 * 2 // 14
7 / 2 // 3.5 (no existe división entera)
7 % 2 // 1 resto
7 ** 2 // 49 potencia
Math.floor(7 / 2) // 3 redondea hacia abajo
Math.trunc(-7 / 2) // -3 corta los decimalesNo hay un operador de división entera como // en Python: se divide y se redondea con Math.floor(), Math.trunc() o Math.round(). Con números positivos, floor y trunc dan lo mismo; con negativos, no.
let contador = 0;
contador++; // 1
contador += 5; // 6=== y ==: usa siempre el triple
=== (igualdad estricta) compara valor y tipo. == convierte los tipos antes de comparar, con reglas difíciles de recordar:
1 === "1" // false
1 == "1" // true
0 == "" // true
0 == "0" // true
"0" == "" // false (¡no es transitivo!)
null == undefined // trueLa regla práctica es usar siempre === y !==. Así una comparación hace lo que parece, y si los tipos no coinciden te enteras en vez de que JavaScript los ajuste en silencio.
<, >, <= y >= comparan números como números, pero dos textos se comparan letra por letra: "2" < "12" es false, porque el carácter "2" va después del "1". Convierte a número antes de comparar valores que vienen como texto.
&&, || y !
&& (y), || (o) y ! (no) combinan condiciones. Pero && y || no devuelven un booleano: devuelven uno de los dos valores. || devuelve el primero que sea verdadero, y && el primero que sea falso (o el último, si todos son verdaderos).
true && "hola" // 'hola'
"" && "hola" // ''
"" || "invitado" // 'invitado'
"Ana" || "invitado" // 'Ana'Por eso || se usa mucho para valores por defecto: const nombre = entrada || "invitado". Los valores que cuentan como falsos son false, 0, "", null, undefined y NaN.
??: valor por defecto solo si falta
El problema de || es que trata el 0 y el texto vacío como si faltaran. ?? (nullish coalescing) solo reemplaza null y undefined:
0 || 10 // 10 ← el 0 se perdió
0 ?? 10 // 0
null ?? 10 // 10
undefined ?? 10 // 10Cuando un 0 o un texto vacío son valores válidos (una cantidad, un descuento, un comentario opcional), usa ??.
Errores comunes
Sumar texto y números
"5" + 3 es "53". Si un valor viene de un formulario, conviértelo con Number() antes de sumar. Con -, * y / la conversión es automática, lo que hace el error del + todavía más difícil de ver.
El resto con números negativos
En JavaScript, -7 % 2 es -1 (en Python es 1): el resultado toma el signo del número de la izquierda. Por eso n % 2 === 1 no detecta los impares negativos. Para saber si un número es impar, pregunta n % 2 !== 0.
Comparar arrays u objetos con ===
[1] === [1] es false: se compara si son el mismo objeto en memoria, no si tienen el mismo contenido. Para comparar contenido hay que recorrerlos (o, en casos simples, comparar JSON.stringify() de ambos).
Ejercicios resueltos
Intenta resolver cada ejercicio antes de abrir la solución: equivocarse y corregir es la parte que más enseña.
1.¿Es par?
Escribe una función esPar(n) que devuelva true si el entero n es par, incluidos los negativos.
esPar(4)→trueesPar(-3)→falseesPar(0)→true
function esPar(n) {
// ...
}Ver soluciónOcultar solución
function esPar(n) {
return n % 2 === 0;
}Un número es par si el resto de dividirlo por 2 es 0, y eso funciona igual con negativos: -4 % 2 es 0 (en rigor -0, pero -0 === 0 es true). La comparación ya es un booleano, así que se devuelve directo, sin if.
2.Año bisiesto
Escribe una función esBisiesto(anio). Un año es bisiesto si es divisible por 4, excepto los divisibles por 100, que solo lo son si además son divisibles por 400.
esBisiesto(2024)→trueesBisiesto(2023)→falseesBisiesto(1900)→falseesBisiesto(2000)→true
function esBisiesto(anio) {
// ...
}Ver soluciónOcultar solución
function esBisiesto(anio) {
return anio % 4 === 0 && (anio % 100 !== 0 || anio % 400 === 0);
}Se traduce la regla tal cual: divisible por 4, y además (no divisible por 100 o divisible por 400). && se evalúa antes que ||, así que los paréntesis dejan explícito cómo se agrupan las condiciones.
3.Descuento opcional
Escribe una función precioConDescuento(precio, descuento) que aplique el descuento (en porcentaje). Si no se indica descuento, se aplica un 10 %. Un descuento de 0 significa que no hay descuento.
precioConDescuento(10000)→9000precioConDescuento(10000, 25)→7500precioConDescuento(10000, 0)→10000
function precioConDescuento(precio, descuento) {
// ...
}Ver soluciónOcultar solución
function precioConDescuento(precio, descuento) {
const porcentaje = descuento ?? 10;
return precio * (100 - porcentaje) / 100;
}Si no se pasa el segundo argumento, descuento vale undefined y ?? lo reemplaza por 10. El caso que distingue una solución correcta de una incorrecta es el tercero: con descuento || 10, un descuento de 0 se trataría como si faltara y el resultado sería 9000 en vez de 10000.
Otra forma de resolverlo es un parámetro por defecto, function precioConDescuento(precio, descuento = 10), que también se aplica solo cuando el argumento es undefined. Se ve en la guía de funciones.