La lliçó anterior va acabar amb una limitació: pesDePrioritat i descriureTasca són declaracions amb nom fix, disponibles sempre i sempre iguals. Però a Nómada Tasques necessitaràs alguna cosa més flexible: una taula que associï cada estat amb la funció que el formata, una llista de validadors que es recorri amb un bucle, o una funció que es triï en temps d'execució segons el que hagi demanat la Marta. Tot això és possible perquè en JavaScript una funció és un valor, exactament igual que un nombre o un text: es pot desar en una variable, ficar en un array, posar dins d'un objecte i passar com a argument. En aquesta lliçó aprendràs les dues maneres d'escriure funcions com a valors —l'expressió de funció i la funció fletxa—, quan fer servir cadascuna i quines diferències reals hi ha entre elles.
Contingut
- Les funcions són valors de primera classe
- L'expressió de funció
- Expressió de funció amb nom
- La funció fletxa: la sintaxi completa
- Retornar un objecte literal des d'una fletxa
- Taula comparativa: declaració vs expressió vs fletxa
- La fletxa i
this: el que necessites saber avui - Un objecte de formatadors per a Nómada Tasques
- Una taula de validadors recorrible
- IIFE: la funció que es crida a si mateixa en néixer
- Quan triar cada forma
- Errors Habituals i Consells
- Exercicis
- Conclusió
- Les funcions són valors de primera classe
Dir que les funcions són ciutadans de primera classe (first-class citizens) significa que el llenguatge les tracta com qualsevol altre valor. Comprova-ho amb la funció de la lliçó anterior:
function pesDePrioritat(prioritat) {
if (prioritat === 'alta') return 3;
if (prioritat === 'mitjana') return 2;
if (prioritat === 'baixa') return 1;
return 0;
}
// 1. Es pot assignar a una variable
const calcularPes = pesDePrioritat;
console.log(calcularPes('alta')); // 3
// 2. Es pot ficar en un array
const operacions = [pesDePrioritat];
console.log(operacions[0]('mitjana')); // 2
// 3. Es pot desar en un objecte
const utilitats = { pes: pesDePrioritat };
console.log(utilitats.pes('baixa')); // 1
// 4. Es pot inspeccionar
console.log(typeof pesDePrioritat); // 'function'
console.log(pesDePrioritat.name); // 'pesDePrioritat'
console.log(pesDePrioritat.length); // 1 (nombre de paràmetres declarats)Fixa't en la línia const calcularPes = pesDePrioritat;: no hi ha parèntesis. No s'està cridant la funció, s'està copiant la referència a la funció. Ara hi ha dos noms apuntant al mateix tros de codi. Això connecta directament amb el que vas aprendre a Variables i Tipus de Dades: les funcions són valors de referència, com els objectes i els arrays.
I aquest és el mecanisme que fa possible tot el que ve després: si una funció és un valor, es pot passar a una altra funció (ho veuràs a Funcions d'Ordre Superior) i es pot triar en temps d'execució.
- L'expressió de funció
Una expressió de funció és una funció escrita al lloc on aniria un valor. La més habitual és assignar-la a una constant:
const estaVencuda = function (dataLimit, estat, avui) {
return dataLimit < avui && estat !== 'feta';
};
console.log(estaVencuda('2026-09-05', 'pendent', '2026-09-20')); // trueTres detalls de sintaxi que convé marcar:
- Després de
functionno hi ha nom. Es diu que és una funció anònima. - La constant
estaVencudaés la que dóna nom pràctic a la funció. - Hi ha punt i coma al final, perquè tota la línia és una assignació (una sentència), no una declaració.
La diferència pràctica més important amb la declaració és quan existeix:
console.log(declarada('alta')); // 3 ✓ funciona
function declarada(p) { return p === 'alta' ? 3 : 1; }
console.log(expressada('alta')); // ✗ ReferenceError: Cannot access 'expressada' before initialization
const expressada = function (p) { return p === 'alta' ? 3 : 1; };Una declaració de funció està a punt abans que comenci l'execució; una expressió assignada a const o let no existeix fins que la línia s'executa. El mecanisme complet (el hoisting i la zona morta temporal) l'estudiaràs a Hoisting i el Context d'Execució. La conseqüència pràctica d'avui: amb expressions, defineix abans d'usar.
Aquesta restricció, que sembla un inconvenient, en realitat és un avantatge: obliga a un ordre de lectura natural de dalt a baix i evita l'estil desordenat en què les funcions apareixen després d'haver-se fet servir.
- Expressió de funció amb nom
Es pot posar un nom a la funció i a més assignar-la a una variable. S'anomena named function expression:
const calcularUrgencia = function calcularUrgenciaInterna(prioritat, diesRestants) {
if (diesRestants < 0) return 100;
return pesDePrioritat(prioritat) * 10 - diesRestants;
};Per a què serveix aquest nom intern, si per cridar-la es fa servir calcularUrgencia?
| Avantatge | Explicació |
|---|---|
| Traces d'error llegibles | Al stack d'un Error apareix calcularUrgenciaInterna en lloc de <anonymous> |
| Autoreferència | Dins del cos pots cridar-te a tu mateixa per aquest nom, útil en recursivitat (vegeu Recursivitat) |
| No contamina fora | calcularUrgenciaInterna només existeix dins del cos; a fora dóna ReferenceError |
console.log(calcularUrgencia.name); // 'calcularUrgenciaInterna'
console.log(typeof calcularUrgenciaInterna); // ✗ ReferenceErrorA la pràctica es fa servir poc, perquè els motors moderns ja infereixen el nom de la variable:
const estaVencuda = function (d, e, a) { return d < a && e !== 'feta'; };
console.log(estaVencuda.name); // 'estaVencuda' ← inferit de la constant
- La funció fletxa: la sintaxi completa
La funció fletxa (arrow function), introduïda a ES2015, és una manera més breu d'escriure una expressió de funció. La seva sintaxi té diverses formes segons el que necessitis, i convé conèixer-les totes perquè les veuràs barrejades en qualsevol codi real.
4.1 Cos de bloc
És la traducció literal d'una expressió de funció: treus function i poses => entre els parèntesis i les claus.
Amb claus, el return és obligatori si vols retornar alguna cosa.
4.2 Retorn implícit
Si el cos és una sola expressió, pots treure les claus i el return. El valor d'aquesta expressió es retorna automàticament:
Aquesta és la forma que més veuràs al codi professional per a funcions petites.
4.3 Un sol paràmetre
Amb exactament un paràmetre, els parèntesis són opcionals:
Molts equips configuren el seu linter per exigir sempre els parèntesis ((text) => ...), perquè així afegir un segon paràmetre no obliga a reescriure la línia. A Qualitat de Codi veuràs com s'automatitza aquesta decisió.
4.4 Sense paràmetres
Els parèntesis buits són obligatoris:
4.5 Resum de formes
| Forma | Sintaxi | Quan fer-la servir |
|---|---|---|
| Bloc | (a, b) => { ...; return x; } |
Diverses sentències, guardes, variables internes |
| Retorn implícit | (a, b) => a + b |
Una sola expressió |
| Un paràmetre | a => a * 2 |
Transformacions simples |
| Sense paràmetres | () => 'valor' |
Constants calculades, fàbriques |
| Objecte literal | (a) => ({ clau: a }) |
Vegeu l'apartat següent |
- Retornar un objecte literal des d'una fletxa
Aquí hi ha un parany sintàctic que confon tothom la primera vegada. Això no funciona com esperes:
const resumir = (titol, hores) => { titol: titol, hores: hores };
console.log(resumir('Actualitzar el web de reserves', 14)); // undefinedEl motor interpreta aquestes claus com un bloc de codi, no com un objecte literal. Dins del bloc, titol: sembla una etiqueta (com els break etiqueta de break, continue i Bucles Imbricats), no hi ha return, i la funció retorna undefined.
La solució és embolcallar l'objecte entre parèntesis, perquè el motor sàpiga que és una expressió:
const resumir = (titol, hores) => ({ titol: titol, hores: hores });
console.log(resumir('Actualitzar el web de reserves', 14));
// { titol: 'Actualitzar el web de reserves', hores: 14 }Regla per recordar-ho: claus = bloc; parèntesis + claus = objecte.
flowchart TD
A["(x) => { ... }"] --> B["Les claus són un BLOC<br/>Necessites return explícit"]
C["(x) => ({ ... })"] --> D["Els parèntesis forcen EXPRESSIÓ<br/>Retorna l'objecte"]
- Taula comparativa: declaració vs expressió vs fletxa
Aquesta és la taula que convé tenir a mà fins que les diferències se't quedin gravades:
| Aspecte | Declaraciófunction f() {} |
Expressióconst f = function () {} |
Fletxaconst f = () => {} |
|---|---|---|---|
| Es pot cridar abans de definir-la | Sí (hoisting complet) | No (TDZ de const/let) |
No (TDZ de const/let) |
| Té nom propi | Sí, sempre | Opcional (anònima o amb nom) | No; s'infereix de la variable |
this propi |
Sí | Sí | No: hereta el de l'entorn |
Objecte arguments |
Sí | Sí | No |
Es pot fer servir amb new |
Sí | Sí | No (TypeError) |
| Retorn implícit | No | No | Sí, si el cos és una expressió |
| Sintaxi més breu | No | No | Sí |
| Ús típic | Funcions principals del mòdul | Funcions assignades condicionalment | Callbacks i funcions d'una línia |
Tres d'aquestes files necessiten aclariment immediat:
argumentsés un objecte llegat que conté tots els arguments rebuts encara que no estiguin declarats com a paràmetres. El veuràs a Paràmetres i Valors de Retorn, juntament amb el seu substitut modern, els paràmetres rest. Les fletxes no el tenen.newserveix per crear objectes amb funcions constructores; és matèria de Prototips i Herència. Amb una fletxa dóna error, i això és deliberat.thises mereix el seu propi apartat.
- La fletxa i
this: el que necessites saber avui
this: el que necessites saber avuithis és una paraula clau el valor de la qual depèn de com es crida la funció. És un tema amb prou matisos per a una lliçó sencera, i la té: Mètodes d'Objecte i this. Avui només necessites gravar-te una frase:
Una funció fletxa no té el seu propi
this: fa servir el de l'àmbit on va ser escrita.
D'aquí se'n deriven les dues conseqüències pràctiques que et trobaràs:
- No facis servir una fletxa com a mètode d'un objecte quan el mètode necessiti accedir a les dades d'aquest objecte. La fletxa no "veurà" l'objecte.
- Sí que has de fer servir una fletxa per a funcions que es passen a una altra funció (callbacks, gestors d'esdeveniments del Mòdul 6), perquè conserva el
thisdel voltant i això sol ser justament el que vols.
Un exemple mínim, només perquè reconeguis el símptoma quan aparegui:
const panell = {
titol: 'Backlog de Taller Nómada',
ambFuncio: function () {
return this.titol; // 'Backlog de Taller Nómada'
},
ambFletxa: () => {
return this.titol; // undefined ← la fletxa no veu l'objecte
}
};
console.log(panell.ambFuncio()); // Backlog de Taller Nómada
console.log(panell.ambFletxa()); // undefinedNo intentis entendre ara per què: només recorda el patró. A 04-02 el desmuntaràs peça a peça. Res del que escriguis en aquest mòdul depèn de this.
- Un objecte de formatadors per a Nómada Tasques
Aquí és on les funcions com a valors comencen a pagar. Al Mòdul 2 formataves cada camp amb switch o cadenes d'if repartits pel fitxer. Ara pots agrupar tots els formatadors en un sol objecte, amb l'avantatge que cadascun es pot substituir, reutilitzar o provar per separat.
'use strict';
const AVUI = '2026-09-20';
const MESOS = ['gen', 'feb', 'mar', 'abr', 'mai', 'jun',
'jul', 'ago', 'set', 'oct', 'nov', 'des'];
const formatadors = {
// '2026-09-30' → '30 set 2026'
data: (iso) => {
const [any, mes, dia] = [iso.slice(0, 4), iso.slice(5, 7), iso.slice(8, 10)];
return `${Number(dia)} ${MESOS[Number(mes) - 1]} ${any}`;
},
// 'en-curs' → 'En curs'
estat: (estat) => {
if (estat === 'pendent') return 'Pendent';
if (estat === 'en-curs') return 'En curs';
if (estat === 'feta') return 'Feta';
return 'Desconegut';
},
// 'alta' → '🔴 Alta'
prioritat: (prioritat) => {
if (prioritat === 'alta') return '🔴 Alta';
if (prioritat === 'mitjana') return '🟠 Mitjana';
if (prioritat === 'baixa') return '🟢 Baixa';
return '⚪ Sense prioritat';
},
// 7.5 → '7,5 h'
hores: (hores) => `${String(hores).replace('.', ',')} h`,
// null → '—'
responsable: (nom) => nom ?? '—'
};
console.log(formatadors.data('2026-09-30')); // 30 set 2026
console.log(formatadors.estat('en-curs')); // En curs
console.log(formatadors.prioritat('alta')); // 🔴 Alta
console.log(formatadors.hores(7.5)); // 7,5 h
console.log(formatadors.responsable(null)); // —Explicació del que aporta aquesta estructura:
- Un sol punt de canvi per a tota la presentació. Si la Marta demana que les dates es mostrin com
30/09/2026, toques una línia. - Es tria el formatador amb una variable.
formatadors[camp](valor)permet formatar un camp el nom del qual no coneixes fins que s'executa el programa. Això ambswitchno es podia fer. - Cada formatador és independent. Al Mòdul 8 podràs provar
formatadors.datasense engegar la resta de l'aplicació.
I així es fa servir la selecció dinàmica, aprofitant el ?? d'Operadors Bàsics:
function formatarCamp(camp, valor) {
const formatador = formatadors[camp];
if (!formatador) return String(valor); // camp sense formatador: valor cru
return formatador(valor);
}
const camps = ['estat', 'prioritat', 'data', 'hores'];
const valors = ['pendent', 'alta', '2026-09-05', 5];
for (let i = 0; i < camps.length; i++) {
console.log(`${camps[i]}: ${formatarCamp(camps[i], valors[i])}`);
}
// estat: Pendent
// prioritat: 🔴 Alta
// data: 5 set 2026
// hores: 5 hEl
const [any, mes, dia] = [...]del formatador de dates és desestructuració d'arrays; s'estudia a Desestructuració d'Arrays. Aquí només significa "assigna el primer element aany, el segon amesi el tercer adia".
- Una taula de validadors recorrible
El segon patró que desbloquegen les funcions com a valors és una llista de regles. Al Mòdul 2, validar una tasca era un bloc de quaranta línies amb if encadenats. Ara cada regla és una entrada d'un array, amb el seu codi i el seu missatge:
const validadors = [
{
regla: 'R2',
missatge: 'El títol és obligatori.',
comprovar: (titol, hores, prioritat, dataLimit) => titol.trim().length > 0
},
{
regla: 'R3',
missatge: 'Les hores han de ser entre 0 i 40.',
comprovar: (titol, hores, prioritat, dataLimit) => hores > 0 && hores <= 40
},
{
regla: 'R6',
missatge: 'La prioritat ha de ser alta, mitjana o baixa.',
comprovar: (titol, hores, prioritat, dataLimit) =>
prioritat === 'alta' || prioritat === 'mitjana' || prioritat === 'baixa'
},
{
regla: 'R4',
missatge: 'La data límit no pot ser anterior a avui.',
comprovar: (titol, hores, prioritat, dataLimit) => dataLimit >= AVUI
}
];
function validarTasca(titol, hores, prioritat, dataLimit) {
const errors = [];
for (let i = 0; i < validadors.length; i++) {
const v = validadors[i];
if (!v.comprovar(titol, hores, prioritat, dataLimit)) {
errors.push(`${v.regla}: ${v.missatge}`);
}
}
return errors;
}
console.log(validarTasca('Pressupost de la fusteria', 5, 'alta', '2026-09-05'));
// [ 'R4: La data límit no pot ser anterior a avui.' ]
console.log(validarTasca(' ', 60, 'urgent', '2026-10-01'));
// [ 'R2: El títol és obligatori.',
// 'R3: Les hores han de ser entre 0 i 40.',
// 'R6: La prioritat ha de ser alta, mitjana o baixa.' ]Llegeix bé el que ha passat aquí: afegir una regla nova ja no vol dir tocar validarTasca, sinó afegir un objecte a l'array. La funció que valida no sap quantes regles hi ha ni què comproven; només sap recórrer-les i cridar-les. Aquesta separació entre el motor i les regles és una de les idees més rendibles de la programació, i a Funcions d'Ordre Superior la portaràs molt més enllà.
- IIFE: la funció que es crida a si mateixa en néixer
Una IIFE (Immediately Invoked Function Expression, expressió de funció invocada immediatament) és una funció que es defineix i s'executa a l'acte:
(function () {
const clau = 'valor privat';
console.log('Inicialitzant Nómada Tasques…');
})();
// Versió amb fletxa
(() => {
console.log('Igual, però més curt.');
})();Els parèntesis exteriors converteixen la declaració en una expressió; els () finals la criden. Es feien servir massivament abans del 2015 per un motiu molt concret: crear un àmbit privat. Abans de let i const, qualsevol var del fitxer es tornava global i podia col·lidir amb un altre script de la pàgina. Embolcallar-ho tot en una IIFE aïllava les variables.
// El patró clàssic dels anys de jQuery
var NomadaTasques = (function () {
var comptador = 0; // invisible des de fora
return {
seguentId: function () { return ++comptador; }
};
})();
console.log(NomadaTasques.seguentId()); // 1
console.log(NomadaTasques.seguentId()); // 2
console.log(typeof comptador); // 'undefined' → està protegitEncara cal? Gairebé mai. Avui tens dues eines millors:
| Necessitat | Solució antiga | Solució moderna |
|---|---|---|
| Aïllar variables d'un fitxer | IIFE | Mòduls ES (05-04) |
| Aïllar variables d'un bloc | IIFE | Un bloc { } amb let/const |
| Estat privat en una funció | IIFE | Closures (03-04) |
Convé reconèixer el patró perquè apareix en moltíssim codi heretat, però en codi nou el normal és no escriure'l.
- Quan triar cada forma
A la pràctica professional, l'elecció es redueix a aquestes pautes:
| Situació | Forma recomanada | Motiu |
|---|---|---|
Funció principal d'un fitxer (validarTasca, crearTasca) |
Declaració o const + expressió |
Nom clar a les traces; totes dues valen, tria un estil i sigues coherent |
| Callback curt d'una línia | Fletxa amb retorn implícit | Màxima brevetat i llegibilitat |
| Funció desada en un objecte de configuració | Fletxa | És un valor entre altres valors |
| Mètode d'un objecte que fa servir les dades de l'objecte | function (o sintaxi de mètode) |
Necessita el seu propi this (vegeu 04-02) |
| Funció recursiva | Declaració | El nom està garantit dins del cos |
| Gestor d'esdeveniment del DOM que fa servir l'element | Depèn | Al Mòdul 6 en veuràs els dos casos |
I una recomanació d'estil que segueixen la majoria d'equips: fes servir const + fletxa per defecte, i declaració només quan vulguis destacar una funció principal del fitxer. L'important no és quina tries, sinó que el fitxer sencer sigui coherent.
Errors Habituals i Consells
1. Cridar una expressió abans de definir-la.
Amb expressions i fletxes: defineix a dalt, fes-ho servir a baix. Sempre.
2. Oblidar el return en fer servir claus en una fletxa.
const doble = (n) => { n * 2; }; // ✗ retorna undefined
const doble = (n) => { return n * 2; }; // ✓
const doble = (n) => n * 2; // ✓ encara millor3. Retornar un objecte sense parèntesis. Ja ho has vist a l'apartat 5: (x) => ({ ... }).
4. Oblidar el punt i coma després d'una expressió de funció. No sol trencar res gràcies a l'ASI, però pot produir errors molt estranys si la línia següent comença per ( o [.
5. Fer servir una fletxa com a mètode que necessita this. El símptoma és un undefined inexplicable en llegir una propietat de l'objecte. Si et passa al Mòdul 4, torna a l'apartat 7.
6. Confondre funcio amb funcio() en desar-la.
const formatadors = { estat: etiquetaEstat() }; // ✗ desa el RESULTAT
const formatadors = { estat: etiquetaEstat }; // ✓ desa la FUNCIÓAquest error és especialment difícil de veure perquè no dóna error de sintaxi: simplement desa undefined o un text on esperaves una funció, i l'errada apareix línies després amb un TypeError: ... is not a function.
7. Consell: si la fletxa ocupa més de dues línies, posa-li claus. El retorn implícit amb expressions llarguíssimes i operadors ternaris encadenats és difícil de llegir i pitjor de depurar (no pots posar un console.log intermedi sense reescriure-la).
8. Consell: dóna nom a les funcions encara que siguin anònimes. Assignar-les a una const amb nom descriptiu no és només estil: és el que fa llegibles els missatges d'error del Mòdul 8.
Exercicis
Exercici 1 — De declaracions a fletxes
Reescriu aquestes tres funcions com a fletxes, fent servir la forma més breu possible en cada cas, i comprova que donen el mateix resultat.
function esFeta(estat) {
return estat === 'feta';
}
function esforc(prioritat, hores) {
return pesDePrioritat(prioritat) * hores;
}
function resumCurt(titol, responsable, hores) {
const nom = responsable === null ? 'sense assignar' : responsable;
return `${titol} (${nom}, ${hores} h)`;
}Exercici 2 — Taula de comparadors
Crea un objecte comparadors les claus del qual siguin 'perHores', 'perData' i 'perPrioritat', i els valors del qual siguin funcions que rebin les dades de dues tasques (per índex) i retornin -1, 0 o 1 segons quina ha d'anar abans. Després escriu elMesUrgent(criteri, ...) que recorri el backlog amb un bucle i retorni l'índex de la tasca que queda primera segons el criteri triat. No facis servir sort (arriba a 04-05).
Exercici 3 — Detectar l'errada
Cadascun d'aquests fragments té un error relacionat amb el que s'ha estudiat a la lliçó. Identifica'l i corregeix-lo.
// a)
const etiqueta = (estat) => { estat.toUpperCase() };
console.log(etiqueta('feta'));
// b)
const novaTasca = (titol, hores) => { titol: titol, hores: hores };
console.log(novaTasca('Cartelleria', 6));
// c)
console.log(pesDe('alta'));
const pesDe = (p) => (p === 'alta' ? 3 : 1);
// d)
const accions = { imprimir: console.log('Hola') };
accions.imprimir('Adeu');Solucions
Exercici 1
'use strict';
const pesDePrioritat = (prioritat) => {
if (prioritat === 'alta') return 3;
if (prioritat === 'mitjana') return 2;
if (prioritat === 'baixa') return 1;
return 0;
};
// Un paràmetre, una expressió → forma mínima
const esFeta = (estat) => estat === 'feta';
// Dos paràmetres, una expressió → retorn implícit
const esforc = (prioritat, hores) => pesDePrioritat(prioritat) * hores;
// Necessita una variable intermèdia → cos de bloc
const resumCurt = (titol, responsable, hores) => {
const nom = responsable ?? 'sense assignar';
return `${titol} (${nom}, ${hores} h)`;
};
console.log(esFeta('feta')); // true
console.log(esforc('alta', 12)); // 36
console.log(resumCurt('Actualitzar el web de reserves', null, 14));
// Actualitzar el web de reserves (sense assignar, 14 h)Comentari: la tercera no s'hauria d'escriure amb retorn implícit. Cabria en una línia fent servir ??, però el bloc deixa clar que hi ha dos passos i permet afegir un console.log de depuració sense reescriure res. Observa a més que responsable ?? 'sense assignar' substitueix el ternari: el ?? d'Operadors Bàsics cobreix null i undefined, que és exactament el cas de la R8.
Exercici 2
const ids = [1, 2, 3, 4, 5, 6];
const prioritats = ['alta', 'mitjana', 'alta', 'baixa', 'mitjana', 'alta'];
const hores = [12, 6, 14, 3, 8, 5];
const datesLimit = ['2026-09-30', '2026-10-15', '2026-10-02',
'2026-09-12', '2026-11-05', '2026-09-05'];
const comparadors = {
// Més hores primer
perHores: (a, b) => {
if (hores[a] > hores[b]) return -1;
if (hores[a] < hores[b]) return 1;
return 0;
},
// Data més propera primer (les cadenes ISO es comparen directament)
perData: (a, b) => {
if (datesLimit[a] < datesLimit[b]) return -1;
if (datesLimit[a] > datesLimit[b]) return 1;
return 0;
},
// Més pes de prioritat primer
perPrioritat: (a, b) => {
const pa = pesDePrioritat(prioritats[a]);
const pb = pesDePrioritat(prioritats[b]);
if (pa > pb) return -1;
if (pa < pb) return 1;
return 0;
}
};
function elMesUrgent(criteri) {
const comparar = comparadors[criteri];
if (!comparar) throw new Error(`Criteri desconegut: ${criteri}`);
let millor = 0;
for (let i = 1; i < ids.length; i++) {
if (comparar(i, millor) < 0) millor = i;
}
return millor;
}
console.log(ids[elMesUrgent('perHores')]); // 3 (14 h)
console.log(ids[elMesUrgent('perData')]); // 6 (2026-09-05)
console.log(ids[elMesUrgent('perPrioritat')]); // 1 (primera 'alta' trobada)Comentari: el patró "màxim amb bandera" és el mateix de Bucles, però ara el criteri de comparació hi entra com a dada. Canviar l'ordre del backlog ja no requereix reescriure el bucle. El throw per al criteri desconegut aplica el principi de fallar aviat de Gestió d'Errors.
Exercici 3
| Fragment | Error | Correcció |
|---|---|---|
| a) | Claus sense return → retorna undefined |
const etiqueta = (estat) => estat.toUpperCase(); |
| b) | Objecte literal sense parèntesis → les claus són un bloc | const novaTasca = (titol, hores) => ({ titol, hores }); |
| c) | Expressió feta servir abans de definir-la → ReferenceError |
Moure la definició abans de la crida |
| d) | Es desa el resultat de console.log('Hola') (undefined), no la funció |
const accions = { imprimir: console.log }; |
A b) apareix l'abreviatura { titol, hores }, equivalent a { titol: titol, hores: hores }; s'estudia a Introducció als Objectes. A d), el símptoma real és un TypeError: accions.imprimir is not a function a la línia següent, lluny de l'error veritable: un recordatori que el punt on peta i el punt on és l'errada rarament coincideixen.
Conclusió
Has après que en JavaScript una funció és un valor de primera classe: la pots assignar a una variable, desar-la en un array o en un objecte, comparar-la per referència i passar-la com a argument. Aquesta propietat, que sembla un detall tècnic, és la que fa possibles els dos patrons que ja has posat en marxa a Nómada Tasques: l'objecte formatadors, que centralitza tota la presentació de camps i permet triar el formatador amb una variable, i l'array validadors, que converteix cada regla de negoci en una dada i deixa validarTasca completament aliena a quantes regles existeixin.
Coneixes les tres maneres d'escriure una funció i les seves diferències reals: la declaració, disponible abans de la seva línia; l'expressió de funció, anònima o amb nom intern, que només existeix a partir de la seva assignació; i la funció fletxa, amb les seves variants de cos de bloc, retorn implícit, un paràmetre i sense paràmetres, a més del truc dels parèntesis per retornar un objecte literal. Saps que la fletxa no té this propi ni arguments ni es pot fer servir amb new, i que aquest primer punt el tancaràs a Mètodes d'Objecte i this. I reconeixes la IIFE, el patró amb què s'aïllaven variables abans que existissin let, const i els mòduls.
Hi ha una cosa que s'ha anat tornant incòmoda pel camí. Els validadors de l'apartat 9 reben quatre paràmetres encara que cadascun en faci servir només un; descriureTasca de la lliçó anterior en rebia vuit; i encara no saps què passa si algú crida una funció amb menys arguments dels declarats, ni com donar un valor per defecte a revisor quan no s'indica. Tot això —com hi entren les dades i com en surten els resultats— és el tema de Paràmetres i Valors de Retorn, on construiràs crearTasca() amb valors per defecte i resumirCarrega() retornant diversos totals d'una sola vegada.
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
