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 decimales

No 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  // true

La 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   // 10

Cuando 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) → true
  • esPar(-3) → false
  • esPar(0) → true
Punto de partida
function esPar(n) {
  // ...
}
Ver solución
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) → true
  • esBisiesto(2023) → false
  • esBisiesto(1900) → false
  • esBisiesto(2000) → true
Punto de partida
function esBisiesto(anio) {
  // ...
}
Ver solución
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) → 9000
  • precioConDescuento(10000, 25) → 7500
  • precioConDescuento(10000, 0) → 10000
Punto de partida
function precioConDescuento(precio, descuento) {
  // ...
}
Ver solución
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.

Practica JavaScript con ejercicios a tu nivel

En Coditer resuelves ejercicios en el navegador, con tests automáticos que revisan tu código y una IA que te da pistas cuando te atascas. Practicar es gratis.