Fins ara el teu codi s'executava en línia recta: de la primera línia a l'última, sense desviar-se mai. Això és suficient per descriure una tasca de Taller Nómada, però no per raonar-hi. La Marta no vol que el programa li repeteixi el que ja sap: vol que li digui quines de les seves tasques estan en risc, si l'Iván pot marcar una tasca com a feta o si el formulari d'alta té una dada invàlida. Tot això són decisions, i una decisió en JavaScript s'escriu amb una sentència condicional. En aquesta lliçó aprendràs a bifurcar el flux amb if, else i else if, a construir condicions compostes que es llegeixin bé, a mantenir el codi pla en lloc d'imbricar-lo fins a fer-lo illegible, i a decidir quan un ternari millora el codi i quan l'empitjora.
Contingut
- Del flux recte a la bifurcació
- La sentència
if else: el camí alternatiuelse if: cadenes de decisió- Condicions compostes amb
&&,||i! - Parèntesis: la diferència entre correcte i llegible
- Condicions sobre valors truthy i falsy
- El problema de la imbricació
- Clàusules de guarda i sortida primerenca
- L'operador ternari i els seus límits
- Cas pràctic: classificar la urgència d'una tasca
- Cas pràctic: validar un canvi d'estat (R6)
- Taula de decisió de les regles de negoci
- Errors Habituals i Consells
- Exercicis
- Conclusió
- Del flux recte a la bifurcació
A Sintaxi i Conceptes Bàsics vas veure que JavaScript executa les sentències de dalt a baix, una darrere l'altra. Una estructura de control trenca aquesta linealitat: permet que certes sentències s'executin només en determinades circumstàncies, o que s'executin moltes vegades.
Les estructures de control es divideixen en dues famílies:
| Família | Què fa | Sentències |
|---|---|---|
| Selecció | Tria un camí entre diversos | if, else, else if, switch |
| Iteració | Repeteix un bloc de sentències | for, while, do...while |
Aquesta lliçó cobreix la selecció amb if. El switch arriba a Sentències Switch i la iteració a Bucles: for, while, do-while.
- La sentència
if
ifLa forma més simple: una condició i un bloc que s'executa només si aquesta condició és certa.
const horesEstimades = 46;
if (horesEstimades > 40) {
console.warn('La tasca supera la setmana laboral completa.');
}
console.log('Comprovació acabada.');Anatomia, peça a peça:
ifés la paraula reservada. No cal que porti el parèntesi enganxat, però sempre s'escriuif (.(horesEstimades > 40)és la condició. Els parèntesis són obligatoris. A dins hi va qualsevol expressió que produeixi un valor; JavaScript el converteix a booleà igual que feiaBoolean()a Conversió de Tipus i Comparacions.{ ... }és el bloc que s'executa si la condició és certa. Ambleticonst, tot el que es declara a dins només existeix a dins.- No porta
;després de la clau de tancament. Unifés una sentència de bloc, no una expressió.
La sortida de l'exemple:
Si canvies 46 per 12, l'avís no apareix i només s'imprimeix la segona línia. El programa ha triat no executar un tros de codi.
2.1 Les claus són opcionals, però posa-les sempre
JavaScript permet ometre les claus quan el cos té una sola sentència:
Funciona, però és una font clàssica d'errors. Mira què passa en afegir-hi una segona línia:
// ✗ PARANY: la segona línia s'executa SEMPRE
if (horesEstimades > 40)
console.warn('Supera les 40 hores.');
console.warn('Revisa-la amb la Marta.');La indentació suggereix que totes dues línies pertanyen a l'if, però la indentació no significa res en JavaScript. Sense claus, l'if només governa la primera sentència; la segona és codi normal que s'executa sempre. L'error és invisible en llegir i evident en executar.
Norma del curs: claus sempre, encara que el cos tingui una sola línia. No costa res i elimina una categoria sencera de fallades.
else: el camí alternatiu
else: el camí alternatiuelse defineix què cal fer quan la condició és falsa. No porta condició pròpia: és "en qualsevol altre cas".
const estat = 'en-curs';
if (estat === 'feta') {
console.log('Tasca completada. No requereix seguiment.');
} else {
console.log('Tasca oberta. Continua al tauler.');
}S'executa exactament un dels dos blocs, mai tots dos ni cap.
flowchart TD
A["estat === 'feta'"] -->|true| B["Tasca completada"]
A -->|false| C["Tasca oberta"]
B --> D["Continua el programa"]
C --> D
else if: cadenes de decisió
else if: cadenes de decisióQuan hi ha més de dos camins, s'encadenen condicions amb else if. Classificar la prioritat d'una tasca en un pes numèric és l'exemple canònic del projecte:
const prioritat = 'mitjana';
let pes;
if (prioritat === 'alta') {
pes = 3;
} else if (prioritat === 'mitjana') {
pes = 2;
} else if (prioritat === 'baixa') {
pes = 1;
} else {
pes = 0;
console.error(`Prioritat desconeguda: "${prioritat}"`);
}
console.log(`Pes de la tasca: ${pes}`); // Pes de la tasca: 2Tres detalls importants:
- Les condicions s'avaluen en ordre i la cadena s'atura a la primera certa. Si
prioritatés'alta', les altres dues comparacions ni tan sols s'executen. L'ordre importa. - L'
elsefinal és la xarxa de seguretat. Captura els valors que no esperaves: un'ALTA'en majúscules, unundefined, una errada d'escriptura. Sense ell,peses quedaria enundefinedi la fallada apareixeria molt més endavant, en un altre lloc, disfressada deNaN. let pes;va abans de l'if. Si declaressisconst pes = 3;dins del bloc, aquesta variable només existiria dins d'aquell bloc i desapareixeria en sortir-ne. Declarar fora i assignar dins és el patró habitual.
Tècnicament else if no és una construcció nova: és un else el cos del qual és un altre if. S'escriu a la mateixa línia per convenció, perquè la cadena es llegeixi com una llista de casos i no com una escala.
- Condicions compostes amb
&&, || i !
&&, || i !A Operadors Bàsics vas aprendre els operadors lògics i el seu curtcircuit. Dins d'un if és on despleguen tota la seva utilitat.
| Operador | Es llegeix | És cert quan |
|---|---|---|
&& |
"i" | Tots dos costats són certs |
|| |
"o" | Almenys un dels costats és cert |
! |
"no" | El valor de la dreta és fals |
La regla R10 del projecte diu: una tasca vençuda (dataLimit passada i estat diferent de 'feta') es destaca. Són dues condicions que s'han de complir alhora, així que s'uneixen amb &&:
const AVUI = '2026-09-20';
const titol = 'Pressupost de la fusteria';
const dataLimit = '2026-09-05';
const estat = 'pendent';
if (dataLimit < AVUI && estat !== 'feta') {
console.error(`VENÇUDA: ${titol} (va vèncer el ${dataLimit})`);
}Recorda de El Projecte del Curs per què dataLimit < AVUI funciona sense conversions: el format ISO 'yyyy-mm-dd' s'ordena alfabèticament igual que cronològicament.
Amb || expressem "qualsevol d'aquestes situacions justifica revisar la tasca":
const responsable = null;
const horesEstimades = 44;
if (responsable === null || horesEstimades > 40) {
console.warn(`"${titol}" necessita revisió de la Marta.`);
}I ! inverteix una condició. Aquestes dues línies són equivalents:
La segona és clarament millor. Fes servir ! per negar variables booleanes, no per negar comparacions: per a això existeixen !==, <= i >=.
const estaArxivada = false;
if (!estaArxivada) {
console.log('La tasca continua visible al tauler.');
}
- Parèntesis: la diferència entre correcte i llegible
&& té més precedència que ||, igual que * la té sobre +. Això vol dir que aquesta condició:
s'agrupa així:
Pot ser que sigui el que volies, o pot ser que no. El problema és que qui llegeixi el codi no ho pot saber. Compara-ho amb l'altra agrupació possible:
Amb prioritat = 'alta' i horesEstimades = 5, la primera versió dona true i la segona false. Són condicions diferents que s'assemblen molt.
Norma: quan una condició barregi && i ||, escriu-hi els parèntesis encara que la precedència ja faci el correcte. No són per al motor: són per a la persona que revisi el codi d'aquí a sis mesos.
Quan una condició creix massa, la millor eina no són més parèntesis sinó variables booleanes amb nom:
const AVUI = '2026-09-20';
const prioritat = 'alta';
const estat = 'pendent';
const dataLimit = '2026-09-30';
const horesEstimades = 12;
const estaVencuda = dataLimit < AVUI && estat !== 'feta';
const esImportant = prioritat === 'alta' || horesEstimades > 20;
const estaOberta = estat !== 'feta';
if (estaOberta && (estaVencuda || esImportant)) {
console.log('Aquesta tasca entra en la revisió diària de la Marta.');
}L'if final ara es llegeix com una frase en català: està oberta, i o bé està vençuda o bé és important. Cada variable intermèdia documenta una idea del negoci i la pots imprimir per separat quan alguna cosa no quadri. Aquesta tècnica —donar nom als trossos d'una condició— és la que més millora la llegibilitat del codi real.
- Condicions sobre valors truthy i falsy
A Conversió de Tipus i Comparacions vas veure els vuit valors falsy: false, 0, -0, 0n, '', null, undefined i NaN. Tota la resta és truthy. Un if aplica exactament aquesta conversió a la seva condició.
Això permet escriure comprovacions molt curtes:
const revisor = null;
if (revisor) {
console.log(`Revisa: ${revisor}`);
} else {
console.log('Tasca sense revisor assignat.');
}Còmode, però perillós, perquè if (valor) fica al mateix sac situacions molt diferents. Observa què passa amb els camps del projecte:
| Comprovació | 0 |
'' |
null |
undefined |
[] |
'0' |
|---|---|---|---|---|---|---|
if (valor) |
✗ no hi entra | ✗ no hi entra | ✗ no hi entra | ✗ no hi entra | ✓ hi entra | ✓ hi entra |
Dues conseqüències directes sobre Nómada Tasques:
horesEstimades pot ser un nombre vàlid i falsy. Si un dia s'admetessin tasques de 0 hores, if (horesEstimades) les tractaria com si el camp faltés. La comprovació honesta és explícita:
const horesEstimades = 0;
if (horesEstimades > 0 && horesEstimades <= 40) {
console.log('Hores vàlides.');
} else {
console.error('R3 incomplerta: les hores han de ser entre 0 (exclòs) i 40.');
}Un array buit és truthy. if (etiquetes) dona true encara que no hi hagi cap etiqueta, perquè l'array existeix. Com que etiquetes és sempre un array (mai null), el que cal mirar és la seva longitud:
const etiquetes = [];
if (etiquetes.length === 0) {
console.log('Tasca sense etiquetar.');
} else {
console.log(`Té ${etiquetes.length} etiqueta/es.`);
}Norma pràctica: fes servir if (valor) només quan de debò vulguis dir "aquí hi ha alguna cosa utilitzable" i cap dels valors falsy sigui legítim per a aquell camp. En tots els altres casos, escriu la comparació completa: === null, > 0, .length === 0, !== ''. El codi guanya en claredat el que perd en brevetat.
- El problema de la imbricació
Un if pot contenir un altre if. La primera vegada que fa falta, el resultat sembla raonable:
// ✗ Difícil de seguir
const estat = 'pendent';
const responsable = 'Iván';
const dataLimit = '2026-09-30';
const AVUI = '2026-09-20';
if (estat !== 'feta') {
if (responsable !== null) {
if (dataLimit < AVUI) {
console.error('Vençuda i assignada.');
} else {
console.log('Assignada i en termini.');
}
} else {
console.warn('Oberta però sense responsable.');
}
} else {
console.log('Acabada.');
}Aquest codi funciona, però té tres problemes seriosos:
- El cas important queda enterrat. Per saber quan s'imprimeix "Vençuda i assignada" cal reconstruir mentalment tres condicions acumulades.
- Els
elsesón lluny del seuif. L'elsede l'última línia pertany al primerif, vint línies més amunt. - Cada nivell nou multiplica els camins. Tres nivells ja donen vuit combinacions possibles.
A aquesta forma se l'anomena codi en fletxa (arrow code), perquè la indentació dibuixa una punta de fletxa cap a la dreta. És un dels senyals més fiables que una lògica necessita reescriure's.
- Clàusules de guarda i sortida primerenca
L'alternativa és la clàusula de guarda: en lloc d'imbricar el cas bo dins de comprovacions successives, es descarten primer els casos excepcionals i es deixa el camí principal al final, sense indentar.
Reescrivim l'exemple anterior com una cadena plana d'else if, ordenada del cas més excloent al més general:
const estat = 'pendent';
const responsable = 'Iván';
const dataLimit = '2026-09-30';
const AVUI = '2026-09-20';
let missatge;
if (estat === 'feta') {
missatge = 'Acabada.';
} else if (responsable === null) {
missatge = 'Oberta però sense responsable.';
} else if (dataLimit < AVUI) {
missatge = 'Vençuda i assignada.';
} else {
missatge = 'Assignada i en termini.';
}
console.log(missatge);Mateix comportament, un sol nivell d'indentació i quatre casos que es llegeixen com una llista. Cada línia respon a una pregunta i la cadena s'atura a la primera resposta afirmativa, de manera que les condicions posteriors poden donar per suposat tot l'anterior: quan s'avalua dataLimit < AVUI, ja sabem amb certesa que la tasca no està feta i que té responsable.
Un segon patró, molt útil en validacions, és acumular el motiu del rebuig en una variable:
const titol = ' ';
const horesEstimades = 52;
let error = '';
if (titol.trim() === '') {
error = 'R2: el títol no pot estar buit.';
} else if (horesEstimades <= 0) {
error = 'R3: les hores han de ser més grans que 0.';
} else if (horesEstimades > 40) {
error = 'R3: les hores no poden superar 40.';
}
if (error !== '') {
console.error(`Tasca rebutjada. ${error}`);
} else {
console.log('Tasca acceptada.');
}titol.trim() elimina els espais dels extrems, de manera que un títol amb només espais es detecta com a buit: exactament el que exigeix la regla R2.
Una nota sobre el nom. "Sortida primerenca" descriu sortir immediatament d'un bloc de lògica quan es detecta un cas invàlid. La seva forma canònica fa servir return dins d'una funció, i aquesta eina arriba a Definició i Crida de Funcions. Mentrestant, la cadena plana d'else if et dona el mateix benefici principal —zero imbricació i casos ordenats— amb el que ja saps. Quan coneguis les funcions, aquest mateix codi es convertirà en tres línies amb return i et resultarà natural.
- L'operador ternari i els seus límits
El ternari condicio ? valorSiCert : valorSiFals que vas veure a Operadors Bàsics és una expressió: produeix un valor. Aquesta és la clau per saber quan fer-lo servir.
Fes-lo servir per assignar o interpolar un valor, on brilla:
const responsable = null;
const estat = 'feta';
const horesEstimades = 12;
const qui = responsable === null ? 'sense assignar' : responsable;
const icona = estat === 'feta' ? '✓' : '○';
console.log(`${icona} Redissenyar la sala polivalent · ${qui} · ${horesEstimades} h`);
// ✓ Redissenyar la sala polivalent · sense assignar · 12 hAmb un if/else caldrien cinc línies i una variable let que després no torna a canviar. El ternari permet mantenir const, que sempre és preferible.
No el facis servir per executar accions. Això funciona però és un abús: el ternari està pensat per produir valors, no per triar efectes secundaris.
// ✗ Abús: el valor de retorn no es fa servir per a res
estat === 'feta' ? console.log('Feta') : console.error('Pendent');
// ✓ Un if/else expressa exactament el que passa
if (estat === 'feta') {
console.log('Feta');
} else {
console.error('Pendent');
}No l'imbriquis més d'una vegada. Un ternari dins d'un altre encara es llegeix si es formata en columna, però tres ja no:
// ✗ Illegible
const pes = prioritat === 'alta' ? 3 : prioritat === 'mitjana' ? 2 : prioritat === 'baixa' ? 1 : 0;
// △ Acceptable si s'alinea, però un if/else if és més clar
const pesAlineat =
prioritat === 'alta' ? 3 :
prioritat === 'mitjana' ? 2 :
prioritat === 'baixa' ? 1 :
0;Quan la cadena de casos creix, la construcció adequada és un if/else if o un switch, que veuràs a la lliçó 02-03.
| Situació | Eina recomanada |
|---|---|
| Assignar un de dos valors | Ternari |
| Triar un text dins d'un template literal | Ternari |
| Executar sentències diferents segons el cas | if / else |
| Tres o més casos sobre la mateixa variable | if / else if o switch |
Condició amb && i || barrejats |
if amb variables booleanes amb nom |
- Cas pràctic: classificar la urgència d'una tasca
La Marta necessita una etiqueta d'urgència que combini dos senyals: la prioritat i els dies que falten per a la data límit. Aquest és el primer tros de lògica de negoci real del projecte.
const AVUI = '2026-09-20';
const titol = 'Redissenyar la sala polivalent';
const prioritat = 'alta';
const estat = 'en-curs';
const dataLimit = '2026-09-30';
// Dies restants: convertim les dates ISO a mil·lisegons i restem.
const MS_PER_DIA = 1000 * 60 * 60 * 24;
const diesRestants = Math.round((new Date(dataLimit) - new Date(AVUI)) / MS_PER_DIA);
// Senyals del negoci, cadascun amb el seu nom
const estaTancada = estat === 'feta';
const estaVencuda = diesRestants < 0;
const esImminent = diesRestants >= 0 && diesRestants <= 3;
const esPrioritaria = prioritat === 'alta';
let urgencia;
if (estaTancada) {
urgencia = 'cap';
} else if (estaVencuda) {
urgencia = 'crítica';
} else if (esImminent && esPrioritaria) {
urgencia = 'crítica';
} else if (esImminent || esPrioritaria) {
urgencia = 'alta';
} else if (diesRestants <= 14) {
urgencia = 'mitjana';
} else {
urgencia = 'baixa';
}
console.log(`${titol}: urgència ${urgencia} (falten ${diesRestants} dies)`);
// Redissenyar la sala polivalent: urgència alta (falten 10 dies)Què cal entendre aquí:
new Date(dataLimit) - new Date(AVUI)aprofita una cosa que ja coneixes: quan es fa servir l'operador-, JavaScript converteix cada data al seu nombre de mil·lisegons des del 1970. Restar-les dona la distància en mil·lisegons; dividir entreMS_PER_DIAla converteix en dies. És l'únic cas del projecte on fem servirDate, tal com es va anunciar a la lliçó 01-08.- L'ordre de la cadena és lògica de negoci, no capritx. Una tasca feta no és mai urgent encara que hagi vençut, així que
estaTancadava primer. Una de vençuda és crítica sense més comprovacions, així que va segona. - Les quatre variables booleanes fan la cadena autoexplicativa. Sense elles, la quarta condició seria
(diesRestants >= 0 && diesRestants <= 3) || prioritat === 'alta', correcta però opaca.
- Cas pràctic: validar un canvi d'estat (R6)
La regla R6 diu que només són vàlides les transicions del cicle de vida. Recorda el diagrama de la lliçó 01-08:
stateDiagram-v2
[*] --> pendent: es crea
pendent --> en_curs: algú comença
en_curs --> feta: es finalitza
en_curs --> pendent: queda aparcada
feta --> en_curs: cal retocar-la
Traduït a condicions: són vàlides quatre transicions i cap més. L'Iván intenta passar una tasca de 'pendent' directament a 'feta', i el programa ho ha de rebutjar amb un motiu comprensible.
const estatActual = 'pendent';
const estatNou = 'feta';
const ES_ESTAT_VALID =
estatNou === 'pendent' || estatNou === 'en-curs' || estatNou === 'feta';
let permes;
let motiu;
if (!ES_ESTAT_VALID) {
permes = false;
motiu = `"${estatNou}" no és un estat del sistema.`;
} else if (estatActual === estatNou) {
permes = false;
motiu = `La tasca ja està en estat "${estatActual}".`;
} else if (estatActual === 'pendent' && estatNou === 'en-curs') {
permes = true;
motiu = 'Algú comença la tasca.';
} else if (estatActual === 'en-curs' && estatNou === 'feta') {
permes = true;
motiu = 'Tasca acabada.';
} else if (estatActual === 'en-curs' && estatNou === 'pendent') {
permes = true;
motiu = 'La tasca queda aparcada.';
} else if (estatActual === 'feta' && estatNou === 'en-curs') {
permes = true;
motiu = 'Es reobre per retocar-la.';
} else {
permes = false;
motiu = `Transició no permesa: ${estatActual} → ${estatNou}.`;
}
if (permes) {
console.log(`✓ ${motiu}`);
} else {
console.error(`✗ ${motiu}`);
}
// ✗ Transició no permesa: pendent → feta.Fixa't en l'estructura: dues guardes al principi (estat inexistent, estat repetit), quatre casos permesos al mig i un else que rebutja tota la resta. Rebutjar per defecte és la política correcta en una validació: si demà algú afegeix un estat nou i n'oblida la transició, el sistema la rebutjarà en lloc d'acceptar-la en silenci.
Aquesta cadena de sis else if és llarga, i hi ha un motiu: cada branca compara dues variables. A la lliçó 02-03 veuràs que un switch no millora aquest cas concret, i al Mòdul 4 el resoldràs amb un objecte de consulta en quatre línies. De moment, aquesta versió és explícita i correcta, que és el que importa.
- Taula de decisió de les regles de negoci
Abans d'escriure un if complicat convé dibuixar una taula de decisió: una fila per cas, una columna per condició i una columna amb el resultat. Aquesta és la de les validacions que Nómada Tasques aplica en acceptar una tasca nova.
| # | Condició | Regla | Resultat si s'incompleix |
|---|---|---|---|
| 1 | titol.trim() !== '' |
R2 | Rebutjar: títol buit |
| 2 | titol.length <= 100 |
R2 | Rebutjar: títol massa llarg |
| 3 | horesEstimades > 0 |
R3 | Rebutjar: hores no positives |
| 4 | horesEstimades <= 40 |
R3 | Rebutjar: supera la setmana laboral |
| 5 | dataLimit >= AVUI |
R4 | Rebutjar: data límit al passat |
| 6 | prioritat ∈ {alta, mitjana, baixa} |
— | Rebutjar: prioritat desconeguda |
| 7 | estat === 'pendent' |
R5 | Rebutjar: una tasca nova neix pendent |
| 8 | responsable és null o de l'equip |
R8 | Rebutjar: responsable no reconegut |
La taula es tradueix gairebé mecànicament a una cadena de guardes: cada fila és un else if que assigna el missatge de rebuig. Escriure-la abans de programar té dos avantatges: descobreixes casos oblidats mentre l'omples, i et dona la llista de proves que executaràs al Mòdul 8.
Errors Habituals i Consells
Fer servir = en lloc de == o ===. L'error clàssic.
= assigna, no compara. L'expressió val 'feta', que és truthy, així que la condició sempre es compleix i, a més, has destruït el valor original. Amb const obtindràs un TypeError que et salvarà; amb let, una fallada silenciosa. Llegeix sempre === en veu alta com a "és igual a" i = com a "rep".
Comparar amb == per costum. '0' == false és true i null == 0 és false. Fes servir === sempre, tal com va quedar establert a la lliçó 01-07.
Posar ; després de la condició.
El ; és el cos buit de l'if, i el bloc següent és un bloc solt que s'executa passi el que passi. No hi ha error ni avís.
Encadenar comparacions com en matemàtiques. if (0 < hores < 40) no fa el que sembla: avalua 0 < hores, obté true o false, i ho compara amb 40 convertint-ho a 1 o 0. Sempre dona true. El correcte és hores > 0 && hores < 40.
Oblidar l'else final. Si una cadena else if assigna una variable, sense else aquesta variable es pot quedar en undefined. Afegeix sempre un cas per defecte, encara que només sigui per registrar un error.
Repetir la variable a cada comparació. prioritat === 'alta' || 'mitjana' no compara amb 'mitjana': avalua prioritat === 'alta' i, si és fals, retorna 'mitjana', que és truthy. La condició es compleix sempre. Cal escriure prioritat === 'alta' || prioritat === 'mitjana'.
Consell: converteix les condicions llargues en booleans amb nom. És la tècnica d'aquesta lliçó que més impacte té en codi real.
Consell: ordena les cadenes del cas més específic al més general. Si el cas general va primer, els específics no s'assoleixen mai.
Exercicis
Exercici 1 — Etiqueta de càrrega de feina
La Marta vol saber d'un cop d'ull si una tasca és assumible. Escriu una cadena if/else if que, a partir d'horesEstimades, assigni a una variable carrega un d'aquests valors, i que rebutgi amb un missatge d'error els valors que incompleixen la regla R3:
| Hores | carrega |
|---|---|
| Menor o igual que 0, o més gran que 40 | 'invàlida' |
| D'1 a 4 | 'lleugera' |
| De 5 a 15 | 'mitjana' |
| De 16 a 40 | 'pesada' |
Prova-ho amb 2, 12, 30 i -3.
Exercici 2 — Semàfor de la tasca
Amb aquestes variables, calcula una variable semafor amb valor '🔴', '🟠' o '🟢' segons aquestes regles, fent servir variables booleanes amb nom perquè l'if final es llegeixi com una frase:
- 🔴 si la tasca no està feta i la seva data límit ja ha passat.
- 🟠 si no està feta, la data no ha passat i la prioritat és
'alta'. - 🟢 en la resta de casos.
const AVUI = '2026-09-20';
const titol = 'Actualitzar el web de reserves';
const estat = 'pendent';
const prioritat = 'alta';
const dataLimit = '2026-10-02';Imprimeix després una línia amb el semàfor i el títol. Resol la part final (triar el text que acompanya el semàfor: 'urgent', 'atenció' o 'en termini') amb un ternari on sigui raonable.
Exercici 3 — Qui pot canviar l'estat
Amplia la validació de la secció 12 amb una regla addicional de Taller Nómada: només el responsable de la tasca o la Marta (coordinadora) en poden canviar l'estat. Afegeix les variables responsable i usuari, i fes que la validació rebutgi el canvi amb un motiu clar quan l'usuari no tingui permís. Ves amb compte amb l'ordre: comprovar el permís ha d'anar abans de comprovar la transició, perquè no té sentit explicar que la transició és invàlida a algú que no la podia tocar.
Prova-ho amb: responsable 'Iván' i usuari 'Lucía' (ha de rebutjar per permís), i responsable 'Iván' i usuari 'Marta' amb transició en-curs → feta (ha de permetre-ho).
Solucions
Exercici 1
const horesEstimades = 12;
let carrega;
if (horesEstimades <= 0 || horesEstimades > 40) {
carrega = 'invàlida';
console.error(`R3 incomplerta: ${horesEstimades} h no és un valor admissible.`);
} else if (horesEstimades <= 4) {
carrega = 'lleugera';
} else if (horesEstimades <= 15) {
carrega = 'mitjana';
} else {
carrega = 'pesada';
}
console.log(`Càrrega: ${carrega}`); // Càrrega: mitjanaLa clau és descartar primer els valors invàlids. Un cop superada aquesta guarda, sabem que horesEstimades és entre 0 (exclòs) i 40, així que les condicions següents només necessiten el límit superior: <= 4, <= 15 i l'else. No cal escriure horesEstimades >= 5 && horesEstimades <= 15, perquè arribar a aquesta branca ja garanteix que és més gran que 4. Aquesta acumulació implícita és el gran avantatge de les cadenes else if davant dels if solts.
Amb -3: entra a la primera branca, carrega val 'invàlida' i es registra l'error. Amb 2: 'lleugera'. Amb 30: 'pesada'.
Exercici 2
const AVUI = '2026-09-20';
const titol = 'Actualitzar el web de reserves';
const estat = 'pendent';
const prioritat = 'alta';
const dataLimit = '2026-10-02';
const estaOberta = estat !== 'feta';
const haVencut = dataLimit < AVUI;
const esPrioritaria = prioritat === 'alta';
let semafor;
if (estaOberta && haVencut) {
semafor = '🔴';
} else if (estaOberta && esPrioritaria) {
semafor = '🟠';
} else {
semafor = '🟢';
}
const nota = semafor === '🔴' ? 'urgent' : semafor === '🟠' ? 'atenció' : 'en termini';
console.log(`${semafor} ${titol} — ${nota}`);
// 🟠 Actualitzar el web de reserves — atencióLes tres variables booleanes converteixen l'if en una lectura directa: "si està oberta i ha vençut...". Sense elles, la primera condició seria estat !== 'feta' && dataLimit < AVUI, que obliga a rellegir dues vegades.
El ternari doble per a nota és al límit del que és acceptable: són tres casos sobre una sola variable i s'alineen visualment. Si hi hagués un quart semàfor, la resposta correcta seria un if/else if o el switch de la lliçó vinent.
Exercici 3
const estatActual = 'en-curs';
const estatNou = 'feta';
const responsable = 'Iván';
const usuari = 'Marta';
const ES_ESTAT_VALID =
estatNou === 'pendent' || estatNou === 'en-curs' || estatNou === 'feta';
const tePermis = usuari === responsable || usuari === 'Marta';
let permes;
let motiu;
if (!tePermis) {
permes = false;
motiu = `${usuari} no pot modificar una tasca de ${responsable}.`;
} else if (!ES_ESTAT_VALID) {
permes = false;
motiu = `"${estatNou}" no és un estat del sistema.`;
} else if (estatActual === estatNou) {
permes = false;
motiu = `La tasca ja està en estat "${estatActual}".`;
} else if (estatActual === 'pendent' && estatNou === 'en-curs') {
permes = true;
motiu = 'Algú comença la tasca.';
} else if (estatActual === 'en-curs' && estatNou === 'feta') {
permes = true;
motiu = 'Tasca acabada.';
} else if (estatActual === 'en-curs' && estatNou === 'pendent') {
permes = true;
motiu = 'La tasca queda aparcada.';
} else if (estatActual === 'feta' && estatNou === 'en-curs') {
permes = true;
motiu = 'Es reobre per retocar-la.';
} else {
permes = false;
motiu = `Transició no permesa: ${estatActual} → ${estatNou}.`;
}
console.log(permes ? `✓ ${motiu}` : `✗ ${motiu}`);
// ✓ Tasca acabada.Amb usuari = 'Lucía' i responsable = 'Iván', la primera guarda talla immediatament: ✗ Lucía no pot modificar una tasca de Iván. I observa que ni tan sols s'avalua si la transició era vàlida, que és just el que demanava l'enunciat.
tePermis es mereix la seva pròpia variable perquè expressa un concepte del negoci —autorització— diferent del concepte de transició vàlida. Quan demà el permís es compliqui (per exemple, permetre-ho també a un revisor assignat), només canvia aquesta línia.
El ternari del console.log està ben emprat: tria un valor —el prefix ✓ o ✗— dins d'una plantilla, que és exactament la seva comesa.
Conclusió
El teu codi ja pren decisions. Saps escriure un if amb claus sempre, afegir-hi un else per al camí alternatiu i encadenar else if per classificar en més de dos casos, aprofitant que cada branca dona per suposat tot el que van descartar les anteriors. Saps combinar condicions amb &&, || i !, posar parèntesis per llegibilitat encara que la precedència ja sigui correcta, i —el més important— donar nom als trossos d'una condició perquè l'if final es llegeixi com una frase del negoci.
També saps evitar dos paranys freqüents: refiar-te de truthy/falsy quan 0, '' o un array buit són valors legítims, i imbricar if dins d'if fins a dibuixar una fletxa al marge. La cadena plana de guardes és la teva eina contra la imbricació, i el ternari la teva eina per assignar un de dos valors, mai per executar accions ni per encadenar quatre casos.
Aplicat al projecte, ja has implementat dues peces reals de Nómada Tasques: la classificació d'urgència que combina prioritat i dies restants, i la validació de transicions d'estat de la regla R6, amb permisos inclosos.
Però fixa't en una cosa: tota aquesta lògica s'aplica a una sola tasca. La Marta té un backlog de sis, i el mes vinent en tindrà quaranta. Copiar el bloc d'urgència quaranta vegades no és una opció. Això es resol a Bucles: for, while, do-while, on aprendràs a repetir un bloc de codi tantes vegades com faci falta i a recórrer totes les tasques del taller per sumar-ne les hores, trobar la més urgent i comptar quantes en porta cada persona. Amb condicionals dins de bucles tindràs, per fi, un programa que raona sobre dades de debò.
Curs de JavaScript: De Principiant a Avançat
Mòdul 1: Introducció a JavaScript
- Què és JavaScript?
- Configuració del teu Entorn de Desenvolupament
- El teu Primer Programa en JavaScript
- Sintaxi i Conceptes Bàsics de JavaScript
- Variables i Tipus de Dades
- Operadors Bàsics
- Conversió de Tipus i Comparacions
- El Projecte del Curs: Nómada Tasques
Mòdul 2: Estructures de Control
- Sentències Condicionals
- Bucles: for, while, do-while
- Sentències Switch
- Control del Flux: break, continue i Bucles Imbricats
- Gestió d'Errors amb try-catch
Mòdul 3: Funcions
- Definició i Crida de Funcions
- Expressions de Funció i Funcions Fletxa
- Paràmetres i Valors de Retorn
- Àmbit i Closures
- Hoisting i el Context d'Execució
- Funcions d'Ordre Superior
- Recursivitat
Mòdul 4: Objectes i Arrays
- Introducció als Objectes
- Mètodes d'Objecte i la Paraula Clau
this - Arrays: Conceptes Bàsics i Mètodes
- Iteració sobre Arrays
- Cercar, Ordenar i Agregar Dades: find, sort i reduce
- Desestructuració d'Arrays
- Desestructuració d'Objectes, Spread i Rest
- JSON i Còpies d'Objectes
Mòdul 5: Objectes i Funcions Avançades
- Prototips i Herència
- Classes i Programació Orientada a Objectes
- Encapsulació: Getters, Setters i Camps Privats
- Mòduls i Importació/Exportació
- JavaScript Asíncron: Callbacks
- Promeses i Async/Await
- El Bucle d'Esdeveniments i la Cua de Microtasques
- Iteradors i Generadors
Mòdul 6: El Model d'Objectes del Document (DOM)
- Introducció al DOM
- Selecció i Manipulació d'Elements del DOM
- Gestió d'Esdeveniments
- Propagació, Delegació i Esdeveniments Personalitzats
- Creació i Eliminació d'Elements del DOM
- Renderitzat de Llistes i Plantilles HTML
- Gestió i Validació de Formularis
Mòdul 7: APIs del Navegador i Temes Avançats
- Emmagatzematge Local i de Sessió
- Fetch API i AJAX
- Peticions Robustes: Errors, Timeouts i AbortController
- WebSockets
- Service Workers i Aplicacions Web Progressives (PWAs)
- APIs del Navegador Essencials
- Introducció a WebAssembly
Mòdul 8: Proves i Depuració
- Depuració de JavaScript
- Qualitat de Codi: ESLint, Prettier i Convencions
- Proves Unitàries amb Jest
- Dobles de Prova: Mocks, Stubs i Spies
- Proves d'Integració
- Proves d'Extrem a Extrem amb Cypress
Mòdul 9: Rendiment i Optimització
- Mesurar Abans d'Optimitzar: DevTools i Web Vitals
- Optimització del Rendiment de JavaScript
- Gestió de Memòria
- Manipulació Eficient del DOM
- Càrrega Diferida i Divisió de Codi
Mòdul 10: Frameworks i Llibreries de JavaScript
- Per Què Existeixen els Frameworks
- Introducció a React
- Gestió d'Estat amb Redux
- Conceptes Bàsics de Vue.js
- Conceptes Bàsics d'Angular
- Triar el Framework Adequat
