En la lección anterior aprendiste a guardar los datos de una tarea de Taller Nómada en variables del tipo adecuado. Guardar está bien, pero un programa que no calcula nada sirve de poco. Los operadores son los símbolos que combinan y transforman valores: sumar horas, calcular porcentajes, decidir si una condición se cumple o proporcionar un valor por defecto cuando falta un dato. En esta lección los recorrerás todos —desde el humilde + hasta los modernos ?? y ?.— y acabarás calculando la carga de trabajo real de Marta, Iván y Lucía.

Contenido

  1. Operadores aritméticos
  2. Incremento y decremento: prefijo y sufijo
  3. Operadores de asignación
  4. Operadores lógicos y cortocircuito
  5. Coalescencia nula: ?? y ??=
  6. Encadenamiento opcional: ?.
  7. El operador ternario ? :
  8. Concatenación frente a template literals
  9. Precedencia de operadores
  10. Aplicación: la carga de horas del equipo
  11. Errores Comunes y Consejos
  12. Ejercicios
  13. Conclusión

  1. Operadores aritméticos

Son los que hacen cálculos numéricos.

Operador Nombre Ejemplo Resultado
+ Suma 12 + 8 20
- Resta 12 - 8 4
* Multiplicación 12 * 2 24
/ División 12 / 8 1.5
% Módulo (resto) 12 % 8 4
** Exponenciación 2 ** 3 8
const horasIvan = 12;
const horasLucia = 8;

console.log(horasIvan + horasLucia);  // 20
console.log(horasIvan - horasLucia);  // 4
console.log(horasIvan / horasLucia);  // 1.5
console.log(horasIvan % horasLucia);  // 4

1.1 El módulo % es más útil de lo que parece

% devuelve el resto de una división entera. Sus dos usos clásicos:

Saber si un número es par o impar:

const numeroTarea = 7;
console.log(numeroTarea % 2);        // 1 → impar
console.log(numeroTarea % 2 === 0);  // false

Repartir en ciclos. En Nómada Tareas lo usaremos para asignar tareas rotando entre las tres personas del equipo:

// El equipo tiene 3 personas: posiciones 0, 1 y 2
console.log(0 % 3); // 0 → Marta
console.log(1 % 3); // 1 → Iván
console.log(2 % 3); // 2 → Lucía
console.log(3 % 3); // 0 → Marta otra vez
console.log(4 % 3); // 1 → Iván

El resto de dividir entre 3 siempre da 0, 1 o 2: exactamente las posiciones del equipo, cíclicamente.

1.2 La división nunca falla

En muchos lenguajes dividir entre cero provoca un error. En JavaScript, no:

console.log(12 / 0);   // Infinity
console.log(-12 / 0);  // -Infinity
console.log(0 / 0);    // NaN

Esto es peligroso porque el programa no se detiene: sigue calculando con Infinity o NaN y el error aparece mucho más tarde, en un sitio que no tiene nada que ver.

const tareasCompletadas = 5;
const tareasTotales = 0; // ¡todavía no hay tareas!

const porcentaje = (tareasCompletadas / tareasTotales) * 100;
console.log(porcentaje); // Infinity — no es un error, pero está mal

La solución es comprobar el divisor antes de dividir, algo que harás cómodamente cuando aprendas condicionales en el Módulo 2.

1.3 El + tiene doble personalidad

Aquí llega la primera gran trampa. + es a la vez suma y concatenación de textos:

console.log(12 + 8);      // 20    → suma numérica
console.log('12' + '8');  // '128' → concatenación de textos
console.log('12' + 8);    // '128' → ¡si uno es texto, concatena!
console.log(12 + '8');    // '128'

La regla es implacable: si alguno de los dos operandos es un string, + concatena. Este comportamiento es la causa número uno de los cálculos incorrectos en principiantes, sobre todo con datos que vienen de un formulario (donde todo llega como texto).

El resto de operadores aritméticos no tienen este problema: intentan convertir a número.

console.log('12' - 8);  // 4  → convierte '12' a número
console.log('12' * 2);  // 24
console.log('12' / 2);  // 6
console.log('alta' * 2); // NaN → no se puede convertir

En Conversión de Tipos y Comparaciones verás exactamente por qué ocurre esto y cómo protegerte.

  1. Incremento y decremento: prefijo y sufijo

++ suma 1 y -- resta 1 a una variable.

let tareasCompletadas = 5;

tareasCompletadas++;
console.log(tareasCompletadas); // 6

tareasCompletadas--;
console.log(tareasCompletadas); // 5

Ambos tienen dos formas, y la diferencia importa solo cuando usas el resultado en la misma expresión:

Forma Nombre Qué hace
x++ Sufija (postfija) Devuelve el valor antiguo y luego incrementa
++x Prefija Incrementa y luego devuelve el valor nuevo
let a = 5;
console.log(a++); // 5 ← devuelve el valor antiguo
console.log(a);   // 6 ← pero ya está incrementada

let b = 5;
console.log(++b); // 6 ← incrementa primero
console.log(b);   // 6

Mnemotecnia: el ++ se ejecuta en la posición en la que está escrito. Si va delante, primero incrementa; si va detrás, primero devuelve.

Consejo práctico: usa ++ y -- en líneas sueltas, nunca dentro de expresiones complejas. Este tipo de código es una fuente inagotable de errores:

let i = 5;
const resultado = i++ + ++i; // 5 + 7 = 12. Ilegible. No lo escribas.

  1. Operadores de asignación

= asigna un valor. Los demás combinan una operación con la asignación:

Operador Equivale a Ejemplo Resultado (partiendo de h = 12)
= h = 8 8
+= h = h + 8 h += 8 20
-= h = h - 8 h -= 8 4
*= h = h * 2 h *= 2 24
/= h = h / 4 h /= 4 3
%= h = h % 5 h %= 5 2
**= h = h ** 2 h **= 2 144
let horasAcumuladas = 0;

horasAcumuladas += 12; // tarea de Iván
horasAcumuladas += 8;  // tarea de Lucía
horasAcumuladas += 6;  // tarea de Marta

console.log(horasAcumuladas); // 26

+= también funciona con textos, y por la misma razón que +:

let resumen = 'Equipo: ';
resumen += 'Marta, ';
resumen += 'Iván, ';
resumen += 'Lucía';
console.log(resumen); // Equipo: Marta, Iván, Lucía

Recuerda que las variables asignadas con estos operadores deben declararse con let: con const obtendrías un TypeError.

  1. Operadores lógicos y cortocircuito

Son tres, y esconden un comportamiento que conviene entender bien.

Operador Nombre Significado informal
&& Y lógico (AND) Ambos deben cumplirse
|| O lógico (OR) Basta con que uno se cumpla
! Negación (NOT) Invierte el valor lógico
const esUrgente = true;
const estaAsignada = false;

console.log(esUrgente && estaAsignada); // false
console.log(esUrgente || estaAsignada); // true
console.log(!esUrgente);                // false

4.1 La evaluación de cortocircuito

JavaScript evalúa estos operadores de izquierda a derecha y se detiene en cuanto conoce el resultado:

  • Con &&: si el primer valor es falso, el resultado ya es falso. No evalúa el segundo.
  • Con ||: si el primer valor es verdadero, el resultado ya es verdadero. No evalúa el segundo.
function avisar() {
  console.log('Aviso enviado a Marta');
  return true;
}

false && avisar(); // No imprime nada: se detiene en el false
true || avisar();  // No imprime nada: se detiene en el true
true && avisar();  // Imprime 'Aviso enviado a Marta'

Esto se usa muchísimo como atajo para "haz esto solo si aquello se cumple":

const esUrgente = true;
esUrgente && console.log('Avisar al equipo de Taller Nómada');

4.2 Lo que devuelven realmente

Aquí está el detalle que casi nadie explica: && y || no devuelven true o false. Devuelven uno de los operandos.

  • a || b devuelve a si a es truthy; si no, devuelve b.
  • a && b devuelve a si a es falsy; si no, devuelve b.
console.log('Iván' || 'sin asignar');  // 'Iván'
console.log('' || 'sin asignar');      // 'sin asignar'
console.log(0 || 40);                  // 40
console.log('alta' && 'media');        // 'media'
console.log(null && 'media');          // null

(Los conceptos truthy y falsy —qué valores se consideran verdaderos o falsos sin serlo— se detallan en la próxima lección. Por ahora basta saber que 0, '', null, undefined y NaN son falsy, y prácticamente todo lo demás es truthy.)

Este comportamiento habilita el patrón clásico del valor por defecto:

const responsableRecibido = '';
const responsable = responsableRecibido || 'Sin asignar';
console.log(responsable); // 'Sin asignar'

Pero cuidado: tiene una trampa importante.

const horasRecibidas = 0; // ¡0 es un valor legítimo!
const horas = horasRecibidas || 8;
console.log(horas); // 8 ← ¡mal! Queríamos 0

Como 0 es falsy, || lo descarta. Para resolver esto exactamente se creó ??.

4.3 El operador ! y el doble !!

! invierte el valor lógico:

const estaHecha = false;
console.log(!estaHecha); // true

Aplicado dos veces, !! convierte cualquier valor a su equivalente booleano:

console.log(!!'Iván');   // true
console.log(!!'');       // false
console.log(!!0);        // false
console.log(!!12);       // true
console.log(!!null);     // false

Es un truco muy extendido, aunque Boolean(valor) expresa lo mismo con más claridad.

  1. Coalescencia nula: ?? y ??=

El operador ?? (ES2020) devuelve el operando derecho solo si el izquierdo es null o undefined. A diferencia de ||, respeta el 0, el '' y el false.

const horasRecibidas = 0;

console.log(horasRecibidas || 8); // 8  ← || descarta el 0
console.log(horasRecibidas ?? 8); // 0  ← ?? lo respeta

Comparativa completa:

Valor izquierdo valor || 'defecto' valor ?? 'defecto'
'Iván' 'Iván' 'Iván'
'' 'defecto' ''
0 'defecto' 0
false 'defecto' false
NaN 'defecto' NaN
null 'defecto' 'defecto'
undefined 'defecto' 'defecto'

Regla práctica: para valores por defecto, usa ??. Usa || solo cuando quieras tratar también el 0 y la cadena vacía como "ausencia de valor" a propósito.

flowchart TD
    A["Necesitas un<br/>valor por defecto"] --> B{"¿El 0, el false<br/>y la cadena vacía<br/>son datos válidos?"}
    B -->|"Sí (horas, contadores)"| C["Usa ??<br/>solo actúa ante<br/>null y undefined"]
    B -->|"No (nombres, textos)"| D["Puedes usar ||<br/>actúa ante cualquier<br/>valor falsy"]
    C --> E["horasEstimadas ?? 8"]
    D --> F["responsable || 'Sin asignar'"]
const responsable = null;
const horasEstimadas = 0;

console.log(responsable ?? 'Sin asignar');  // 'Sin asignar'
console.log(horasEstimadas ?? 8);           // 0 — correcto

5.1 Asignación con ??=

??= asigna un valor solo si la variable es null o undefined:

let revisor = null;
revisor ??= 'Marta';
console.log(revisor); // 'Marta'

let responsable = 'Lucía';
responsable ??= 'Marta';
console.log(responsable); // 'Lucía' — no se toca

Equivale a if (revisor === null || revisor === undefined) { revisor = 'Marta'; }, pero en una línea.

Existen también ||= y &&= con la misma lógica aplicada a truthy/falsy.

5.2 Una restricción de sintaxis

No puedes mezclar ?? con && o || sin paréntesis: es un SyntaxError deliberado, para evitar ambigüedades.

// const x = a || b ?? c;    // SyntaxError
const x = (a || b) ?? c;     // Correcto: los paréntesis aclaran la intención

  1. Encadenamiento opcional: ?.

El operador ?. (ES2020) accede a una propiedad solo si el valor anterior no es null ni undefined. Si lo es, devuelve undefined en lugar de lanzar un error.

El problema que resuelve:

const tarea = { titulo: 'Rediseñar la sala', responsable: null };

// console.log(tarea.responsable.length); // TypeError: Cannot read properties of null

Ese TypeError detiene el programa entero. Con ?.:

console.log(tarea.responsable?.length); // undefined — sin error

Se puede encadenar tantas veces como haga falta:

const tarea = { titulo: 'Montar la exposición' };

console.log(tarea.revision?.autor);         // undefined
console.log(tarea.revision?.autor?.nombre); // undefined

Sin ?., la segunda línea lanzaría un TypeError en cuanto tarea.revision fuese undefined.

Se combina de maravilla con ??:

const tarea = { titulo: 'Revisar facturas', responsable: null };
const nombre = tarea.responsable?.nombre ?? 'Sin asignar';
console.log(nombre); // 'Sin asignar'

Aviso importante: ?. no es una excusa para no comprobar los datos. Si lo pones en todas partes, ocultarás errores reales en lugar de resolverlos. Úsalo donde de verdad sea legítimo que el valor falte.

El uso completo de ?. con objetos anidados, arrays (tarea?.etiquetas?.[0]) y llamadas a funciones (tarea.guardar?.()) se retomará en el Módulo 4, cuando trabajes con objetos de verdad.

  1. El operador ternario ? :

Es el único operador de JavaScript que toma tres operandos. Su forma:

condicion ? valorSiVerdadero : valorSiFalso
const horasEstimadas = 12;
const tipoTarea = horasEstimadas > 8 ? 'larga' : 'corta';
console.log(tipoTarea); // 'larga'

Se lee como una pregunta: ¿horasEstimadas > 8? Entonces 'larga'; si no, 'corta'.

La gran ventaja frente a un if es que el ternario es una expresión: produce un valor y por tanto puede asignarse, pasarse como argumento o interpolarse.

const responsable = 'Marta';
const horas = 6;

console.log(`${responsable} tiene una tarea ${horas > 8 ? 'larga' : 'corta'}`);
// Marta tiene una tarea corta

Se pueden encadenar, aunque conviene no abusar:

const horasEstimadas = 12;

const categoria =
  horasEstimadas > 16 ? 'proyecto' :
  horasEstimadas > 8  ? 'larga' :
  horasEstimadas > 2  ? 'media' :
                        'rápida';

console.log(categoria); // 'larga'

Alineado así se lee bien, pero a partir de tres o cuatro casos es mejor un switch o un if/else, que verás en el Módulo 2.

Cuándo usar cada uno:

Situación Herramienta
Elegir entre dos valores para asignarlos Ternario
Insertar una decisión dentro de un texto Ternario
Ejecutar varias sentencias según la condición if/else
Muchos casos sobre el mismo valor switch

  1. Concatenación frente a template literals

Ya conoces las dos formas de componer texto. Comparémoslas de frente:

const responsable = 'Iván';
const horas = 12;
const fechaLimite = '2026-09-30';

// Concatenación con +
const conConcatenacion =
  'Tarea de ' + responsable + ': ' + horas + ' h, vence el ' + fechaLimite;

// Template literal
const conPlantilla =
  `Tarea de ${responsable}: ${horas} h, vence el ${fechaLimite}`;
Aspecto Concatenación + Template literal
Legibilidad Baja: el texto se rompe Alta: el texto se lee entero
Espacios Fáciles de olvidar Se ven en el propio texto
Expresiones Requieren paréntesis ${horas * 2} directamente
Saltos de línea Con \n Reales, escribiendo Intro
Riesgo de concatenar sin querer Alto Nulo: todo se convierte a texto

Ese último punto es importante. Con + puedes acabar sumando por accidente:

const horasIvan = 12;
const horasLucia = 8;

console.log('Total: ' + horasIvan + horasLucia);   // 'Total: 128' ← ¡mal!
console.log('Total: ' + (horasIvan + horasLucia)); // 'Total: 20'  ← con paréntesis
console.log(`Total: ${horasIvan + horasLucia}`);   // 'Total: 20'  ← sin ambigüedad

Usa template literals siempre que combines texto y variables. No hay ningún motivo para no hacerlo.

  1. Precedencia de operadores

Cuando una expresión mezcla operadores, JavaScript aplica un orden fijo llamado precedencia. De mayor a menor prioridad, en lo que te afecta ahora:

Nivel Operadores Asociatividad Ejemplo
1 () agrupación (2 + 3) * 420
2 ?. acceso opcional Izquierda tarea?.titulo
3 ++ -- sufijos i++
4 ! ++ -- prefijos, typeof Derecha !estaHecha
5 ** Derecha 2 ** 3 ** 2512
6 * / % Izquierda 2 + 3 * 414
7 + - Izquierda 10 - 3 - 25
8 < > <= >= Izquierda 12 > 8
9 == != === !== Izquierda 'alta' === 'alta'
10 && Izquierda a && b
11 || y ?? Izquierda a || b
12 ? : ternario Derecha x > 0 ? 'sí' : 'no'
13 = += -= ??= Derecha x += 1

Ejemplos que aclaran las reglas:

console.log(2 + 3 * 4);        // 14, no 20: * tiene más precedencia que +
console.log((2 + 3) * 4);      // 20: los paréntesis mandan
console.log(10 - 3 - 2);       // 5: - es asociativo por la izquierda → (10-3)-2
console.log(2 ** 3 ** 2);      // 512: ** es asociativo por la derecha → 2**(3**2)
console.log(!true && false);   // false: ! se aplica antes que &&

Un caso realista en Nómada Tareas:

const horasIvan = 12;
const horasLucia = 8;
const horasMarta = 6;

// Media del equipo: ¿qué crees que da?
console.log(horasIvan + horasLucia + horasMarta / 3);   // 22 ← ¡mal!
console.log((horasIvan + horasLucia + horasMarta) / 3); // 8.67 ← correcto

En el primer caso, / se aplica antes que +, así que solo se dividen las horas de Marta.

Consejo definitivo: no memorices la tabla. Usa paréntesis. Cuestan dos caracteres y eliminan cualquier duda, tanto para el motor como para quien lea tu código. Nadie ha criticado nunca un paréntesis de más; muchos errores vienen de uno de menos.

  1. Aplicación: la carga de horas del equipo

Vamos a juntarlo todo en un caso real de Taller Nómada. Marta quiere saber cómo está repartida la carga de trabajo antes de asignar tareas nuevas.

'use strict';

// --- Datos de partida ---------------------------------------------
const MAX_HORAS_SEMANA = 40;

const responsable = 'Iván';
const horasTarea1 = 12;   // Rediseñar la sala polivalente
const horasTarea2 = 8;    // Cartelería del taller de serigrafía
const horasTarea3 = 4.5;  // Revisar el catálogo de otoño

// Este dato podría no llegar (por ejemplo, si la tarea aún no se ha estimado)
const horasTarea4 = null;

// --- Cálculos ------------------------------------------------------

// 1. Horas asignadas. Con ?? tratamos la estimación que falta como 0
const horasAsignadas =
  horasTarea1 + horasTarea2 + horasTarea3 + (horasTarea4 ?? 0);

// 2. Horas libres (podría salir negativo si está sobrecargado)
const horasLibres = MAX_HORAS_SEMANA - horasAsignadas;

// 3. Porcentaje de ocupación, redondeado
const porcentajeOcupacion = Math.round((horasAsignadas / MAX_HORAS_SEMANA) * 100);

// 4. Estado de la carga con un ternario encadenado
const estadoCarga =
  porcentajeOcupacion >= 100 ? 'sobrecargado' :
  porcentajeOcupacion >= 75  ? 'alto' :
  porcentajeOcupacion >= 40  ? 'equilibrado' :
                               'con margen';

// 5. ¿Puede aceptar una tarea nueva de 8 horas?
const HORAS_TAREA_NUEVA = 8;
const puedeAceptarla = horasLibres >= HORAS_TAREA_NUEVA;

// --- Salida --------------------------------------------------------
console.log(`=== Carga semanal de ${responsable} ===`);
console.log(`Asignadas: ${horasAsignadas} h de ${MAX_HORAS_SEMANA} h`);
console.log(`Libres:    ${horasLibres} h`);
console.log(`Ocupación: ${porcentajeOcupacion}% (${estadoCarga})`);
console.log(
  `¿Puede asumir ${HORAS_TAREA_NUEVA} h más? ${puedeAceptarla ? 'Sí' : 'No'}`
);

// 6. Aviso solo si está en zona de riesgo, usando cortocircuito
porcentajeOcupacion >= 75 &&
  console.warn(`Atención: ${responsable} está al ${porcentajeOcupacion}%`);

Salida:

=== Carga semanal de Iván ===
Asignadas: 24.5 h de 40 h
Libres:    15.5 h
Ocupación: 61% (equilibrado)
¿Puede asumir 8 h más? Sí

Repasemos las decisiones que se han tomado:

  1. horasTarea4 ?? 0 trata la estimación ausente como cero horas. Con || habría funcionado igual aquí, pero si la estimación fuese legítimamente 0, || la habría sustituido por 0 igualmente y en otros contextos daría problemas. ?? expresa exactamente la intención: "si no hay dato, usa 0".
  2. Los paréntesis en (horasAsignadas / MAX_HORAS_SEMANA) * 100 no son estrictamente necesarios (/ y * tienen la misma precedencia y se evalúan de izquierda a derecha), pero dejan clarísima la intención.
  3. Math.round evita mostrar 61.25%.
  4. El ternario encadenado clasifica la carga en cuatro tramos. Está alineado para que se lea como una tabla.
  5. puedeAceptarla es un booleano con nombre de afirmación; en la salida se convierte a texto con otro ternario.
  6. El cortocircuito && ejecuta el aviso solo si se supera el umbral. Aquí no se ejecuta, porque 61 >= 75 es falso.

Errores Comunes y Consejos

Errores comunes

  • Sumar texto sin querer. '12' + 8 da '128'. Los datos de formularios llegan siempre como texto; conviértelos antes de operar.
  • Olvidar los paréntesis en un promedio. a + b + c / 3 no es la media. Es el error de cálculo más repetido del mundo.
  • Usar || para valores por defecto numéricos. horas || 8 convierte un 0 legítimo en 8. Usa ??.
  • Dividir sin comprobar el divisor. x / 0 da Infinity silenciosamente y contamina todos los cálculos posteriores.
  • Mezclar ?? con || o && sin paréntesis. Es un SyntaxError.
  • Abusar de x++ dentro de expresiones. i++ + ++i es un acertijo, no código.
  • Poner ?. en todas partes. Silencia errores reales. Úsalo solo donde el valor pueda faltar legítimamente.
  • Confundir = con == o ===. if (estado = 'hecha') asigna en lugar de comparar, y siempre resulta verdadero.

Consejos

  • Usa paréntesis siempre que haya más de un operador. La claridad vale más que la brevedad.
  • ?? para valores por defecto, || solo cuando quieras descartar también 0 y ''.
  • Template literals para todo texto compuesto. Elimina de un plumazo los errores de concatenación.
  • El ternario, para elegir un valor. Si necesitas ejecutar varias instrucciones, usa if.
  • Nombra los resultados intermedios. const porcentajeOcupacion = ... es infinitamente más legible que meter el cálculo entero dentro de un console.log.
  • Redondea al mostrar, no al calcular. Si redondeas en medio de una cadena de cálculos, acumulas error.

Ejercicios

Ejercicio 1: Predice el resultado

Escribe qué imprime cada línea y por qué:

console.log(2 + 3 * 4);            // A
console.log('8' + 4);              // B
console.log('8' - 4);              // C
console.log(10 % 3);               // D
console.log(2 ** 3 ** 2);          // E

let i = 5;
console.log(i++);                  // F
console.log(i);                    // G

console.log(0 || 40);              // H
console.log(0 ?? 40);              // I
console.log('' ?? 'Sin asignar');  // J
console.log(null ?? 'Sin asignar');// K
console.log(!!'hecha');            // L

Ejercicio 2: Reparto rotativo de tareas

El equipo de Taller Nómada tiene tres personas en este orden: posición 0 = Marta, 1 = Iván, 2 = Lucía. Las tareas se asignan por turnos según su número.

Escribe un script que, dado un numeroTarea, calcule e imprima:

  1. La posición del equipo a la que corresponde (usa %).
  2. Si el número de tarea es par o impar.
  3. Un mensaje con template literal del estilo: La tarea 7 corresponde a la posición 1 (número impar).

Pruébalo con los números 5, 6 y 7.

Ejercicio 3: Informe de carga de Lucía

Escribe un script que calcule la carga semanal de Lucía con estos datos:

  • Máximo semanal: 40 horas.
  • Tareas asignadas: 10, 6.5 y 3 horas.
  • Una cuarta tarea cuya estimación todavía no existe (vale null).
  • Ya ha dedicado 12 horas de las asignadas.

Calcula y muestra:

  1. Total de horas asignadas (la estimación ausente cuenta como 0, usando ??).
  2. Horas pendientes de dedicar.
  3. Porcentaje de avance sobre lo asignado, redondeado a entero.
  4. Porcentaje de ocupación sobre el máximo semanal, redondeado.
  5. Si puede asumir una tarea nueva de 20 horas (booleano mostrado como "Sí"/"No" con un ternario).
  6. Un aviso con console.warn, usando cortocircuito &&, solo si la ocupación supera el 40%.

Soluciones

Ejercicio 1

Línea Resultado Explicación
A 14 * tiene más precedencia que +: 2 + (3*4)
B '84' Uno de los operandos es texto: + concatena
C 4 - no concatena: convierte '8' a número
D 1 El resto de dividir 10 entre 3
E 512 ** asocia por la derecha: 2 ** (3**2) = 2**9
F 5 Forma sufija: devuelve el valor antiguo
G 6 Pero la variable ya está incrementada
H 40 0 es falsy, así que || pasa al segundo operando
I 0 ?? solo actúa ante null o undefined
J '' La cadena vacía no es null ni undefined
K 'Sin asignar' null sí activa ??
L true !! convierte a booleano; un texto no vacío es truthy

Ejercicio 2

'use strict';

const numeroTarea = 7;

// 1. Posición en el equipo (3 personas: 0, 1, 2)
const TAMANO_EQUIPO = 3;
const posicion = numeroTarea % TAMANO_EQUIPO;

// 2. Par o impar
const esPar = numeroTarea % 2 === 0;
const paridad = esPar ? 'par' : 'impar';

// 3. Mensaje
console.log(
  `La tarea ${numeroTarea} corresponde a la posición ${posicion} (número ${paridad}).`
);

Resultados:

numeroTarea % 3 Posición Paridad
5 5 % 3 2 (Lucía) impar
6 6 % 3 0 (Marta) par
7 7 % 3 1 (Iván) impar

Ejercicio 3

'use strict';

// --- Datos ---------------------------------------------------------
const MAX_HORAS_SEMANA = 40;
const responsable = 'Lucía';

const horasTarea1 = 10;
const horasTarea2 = 6.5;
const horasTarea3 = 3;
const horasTarea4 = null;   // todavía sin estimar

const horasDedicadas = 12;

// --- Cálculos ------------------------------------------------------
const horasAsignadas =
  horasTarea1 + horasTarea2 + horasTarea3 + (horasTarea4 ?? 0);

const horasPendientes = horasAsignadas - horasDedicadas;

const porcentajeAvance = Math.round((horasDedicadas / horasAsignadas) * 100);
const porcentajeOcupacion = Math.round((horasAsignadas / MAX_HORAS_SEMANA) * 100);

const HORAS_TAREA_NUEVA = 20;
const horasLibres = MAX_HORAS_SEMANA - horasAsignadas;
const puedeAceptarla = horasLibres >= HORAS_TAREA_NUEVA;

// --- Salida --------------------------------------------------------
console.log(`=== Carga semanal de ${responsable} ===`);
console.log(`Asignadas:  ${horasAsignadas} h`);
console.log(`Dedicadas:  ${horasDedicadas} h`);
console.log(`Pendientes: ${horasPendientes} h`);
console.log(`Avance:     ${porcentajeAvance}%`);
console.log(`Ocupación:  ${porcentajeOcupacion}% de ${MAX_HORAS_SEMANA} h`);
console.log(
  `¿Puede asumir ${HORAS_TAREA_NUEVA} h más? ${puedeAceptarla ? 'Sí' : 'No'}`
);

porcentajeOcupacion > 40 &&
  console.warn(`Atención: ${responsable} supera el 40% de ocupación.`);

Salida:

=== Carga semanal de Lucía ===
Asignadas:  19.5 h
Dedicadas:  12 h
Pendientes: 7.5 h
Avance:     62%
Ocupación:  49% de 40 h
¿Puede asumir 20 h más? Sí
⚠ Atención: Lucía supera el 40% de ocupación.

Puntos a destacar:

  • horasTarea4 ?? 0 neutraliza el dato ausente. Sin ese operador, null acabaría convirtiéndose a 0 de todos modos por coerción implícita, pero escribirlo de forma explícita documenta la intención y no depende de una conversión automática que quizá no controlas.
  • Los paréntesis en los porcentajes garantizan que primero se divide y después se multiplica por 100.
  • El cálculo de puedeAceptarla: horasLibres vale 40 - 19.5 = 20.5, y 20.5 >= 20 es true, así que el resultado es "Sí" por un margen muy justo de media hora. Si hubieras estimado la cuarta tarea en solo una hora, la respuesta habría cambiado. Este es exactamente el tipo de cálculo al filo que conviene que haga el programa y no una persona con una calculadora.

Conclusión

Ya sabes operar con datos. Manejas los aritméticos (+ - * / % **), incluido el módulo para repartos cíclicos, y conoces la doble personalidad del +. Distingues las formas prefija y sufija de ++ y --. Usas los operadores de asignación compuestos (+=, -=, *=...). Entiendes los lógicos &&, || y !, su evaluación de cortocircuito y el hecho de que devuelven un operando, no un booleano. Sabes cuándo usar ?? en lugar de || para valores por defecto, y aplicar ??= y ?. para trabajar con datos que pueden faltar. Empleas el ternario para elegir valores dentro de expresiones, prefieres los template literals a la concatenación, y sobre todo has aprendido la lección más rentable de todas: cuando dudes de la precedencia, pon paréntesis.

Con todo ello has construido el primer cálculo útil de Nómada Tareas: el informe de carga semanal de un miembro del equipo de Taller Nómada.

Pero has visto aparecer un fantasma varias veces: '8' + 4 da '84', null se convierte en 0 al sumar, 0 es falsy y '' también. Ese es el terreno donde más se tropieza. En la siguiente lección, Conversión de Tipos y Comparaciones, lo despejarás por completo: coerción implícita y explícita, la lista exacta de valores falsy y la diferencia entre == y ===. Es la lección que evita la mayoría de los errores de un principiante.

Curso de JavaScript: De Principiante a Avanzado

Módulo 1: Introducción a JavaScript

Módulo 2: Estructuras de Control

Módulo 3: Funciones

Módulo 4: Objetos y Arrays

Módulo 5: Objetos y Funciones Avanzadas

Módulo 6: El Modelo de Objetos del Documento (DOM)

Módulo 7: APIs del Navegador y Temas Avanzados

Módulo 8: Pruebas y Depuración

Módulo 9: Rendimiento y Optimización

Módulo 10: Frameworks y Librerías de JavaScript

Módulo 11: Proyecto Final

© Copyright 2026. Todos los derechos reservados