A la lliçó anterior va aparèixer diverses vegades un fantasma: '8' + 4 dona '84', 0 es comporta com si fos fals i null es converteix en 0 en sumar. Tot això té un nom: coerció de tipus. És el mecanisme pel qual JavaScript converteix automàticament valors d'un tipus a un altre, i és —sense exagerar— la font de la majoria dels errors desconcertants d'un principiant. En aquesta lliçó el desbrossaràs completament: quan converteix JavaScript pel seu compte, com convertir tu de manera explícita, quins valors es consideren certs o falsos, i per què has de fer servir sempre ===. En acabar sabràs tractar amb seguretat les dades d'un formulari de tasca, que arriben sempre com a text.
Contingut
- Per què existeix la conversió de tipus
- Conversió explícita a nombre
- Conversió explícita a text
- Conversió explícita a booleà: truthy i falsy
- Conversió implícita (coerció)
- Operadors de comparació
==enfront de===- Comparar cadenes i comparar nombres
- Comparar objectes: el parany de la referència
Object.isi els casos límit- Regles pràctiques d'higiene
- Aplicació: validar les dades d'un formulari de tasca
- Errors Habituals i Consells
- Exercicis
- Conclusió
- Per què existeix la conversió de tipus
JavaScript es va dissenyar per ser tolerant. El 1995 es buscava un llenguatge que no fallés davant de dades imperfectes: millor un resultat estrany que una pàgina trencada. Per això, quan li demanes una cosa que no encaixa —sumar un text amb un nombre, per exemple— no protesta: converteix el que pot i tira endavant.
Hi ha dos tipus de conversió:
| Tipus | Qui la fa | Exemple |
|---|---|---|
| Explícita | Tu, a propòsit | Number('12') → 12 |
| Implícita (coerció) | JavaScript, pel seu compte | '12' * 2 → 24 |
L'explícita és la teva aliada. La implícita és la que cal conèixer per no ser-ne víctima.
Només existeixen tres destinacions possibles de conversió: nombre, text i booleà. Tota la resta són variants d'aquestes tres.
- Conversió explícita a nombre
2.1 Number()
Converteix el valor sencer a nombre. Si no pot, retorna NaN.
console.log(Number('12')); // 12
console.log(Number('12.5')); // 12.5
console.log(Number(' 12 ')); // 12 ← ignora els espais del voltant
console.log(Number('')); // 0 ← compte! la cadena buida dona 0
console.log(Number(' ')); // 0 ← només espais, també 0
console.log(Number('12h')); // NaN ← el valor sencer ha de ser numèric
console.log(Number('alta')); // NaN
console.log(Number(true)); // 1
console.log(Number(false)); // 0
console.log(Number(null)); // 0 ← compte!
console.log(Number(undefined)); // NaNDos resultats mereixen atenció especial perquè provoquen errors reals:
Number('')és0, noNaN. Si un usuari deixa buit el camp d'hores, obtindràs0en lloc d'un avís d'error.Number(null)és0peròNumber(undefined)ésNaN. Una altra incoherència històrica que cal conèixer.
2.2 parseInt() i parseFloat()
Aquestes funcions són més permissives: llegeixen el nombre des del principi i s'aturen al primer caràcter no vàlid.
console.log(parseInt('12h')); // 12 ← es queda amb el que entén
console.log(parseInt('12.9')); // 12 ← trunca els decimals
console.log(parseFloat('12.9h')); // 12.9 ← conserva decimals
console.log(parseInt('h12')); // NaN ← no comença per nombre
console.log(parseInt('')); // NaN ← aquí sí que dona NaN, no 0Fes servir sempre parseInt amb la base 10 com a segon argument. És un hàbit heretat d'una època en què un text que començava per 0 s'interpretava en octal:
Comparativa:
| Valor | Number() |
parseInt() |
parseFloat() |
|---|---|---|---|
'12' |
12 |
12 |
12 |
'12.9' |
12.9 |
12 |
12.9 |
'12h' |
NaN |
12 |
12 |
'12 hores' |
NaN |
12 |
12 |
'' |
0 |
NaN |
NaN |
' ' |
0 |
NaN |
NaN |
'alta' |
NaN |
NaN |
NaN |
true |
1 |
NaN |
NaN |
null |
0 |
NaN |
NaN |
Quina fer servir: Number() quan exigeixis que el valor sencer sigui un nombre (el més habitual en validar dades). parseInt/parseFloat quan vulguis extreure un nombre d'un text que porta unitats ('12px', '8 hores').
2.3 El truc del + unari
Posar un + davant d'un valor el converteix a nombre, exactament igual que Number():
És breu i molt utilitzat, però Number() es llegeix millor i no es confon amb una suma. Reconeix-lo quan el vegis; escriu Number().
2.4 Validar un nombre de debò
Combinant tot l'anterior, així es comprova correctament que un text conté un nombre utilitzable:
const entrada = '12.5';
const hores = Number(entrada);
const esNombreValid = !Number.isNaN(hores) && entrada.trim() !== '';
console.log(esNombreValid); // trueCalen les dues comprovacions: Number.isNaN descarta els textos no numèrics, i el trim() !== '' descarta la cadena buida, que Number() convertiria en 0 sense protestar.
- Conversió explícita a text
3.1 String()
Converteix qualsevol valor a text. Funciona amb tot, inclosos null i undefined.
console.log(String(12)); // '12'
console.log(String(12.5)); // '12.5'
console.log(String(true)); // 'true'
console.log(String(null)); // 'null'
console.log(String(undefined)); // 'undefined'
console.log(String(NaN)); // 'NaN'
console.log(String([1, 2, 3])); // '1,2,3'
console.log(String({ a: 1 })); // '[object Object]'Aquesta última línia és un clàssic: si algun cop veus [object Object] a la pantalla, has convertit un objecte a text sense voler.
3.2 .toString()
És un mètode del valor mateix. Fa el mateix que String(), amb una diferència crítica:
console.log((12).toString()); // '12'
console.log(true.toString()); // 'true'
// console.log(null.toString()); // TypeError
// console.log(undefined.toString()); // TypeErrorString() és més segur perquè no llança mai cap error. .toString() falla davant de null i undefined, que són precisament els casos en què més falta et fa no fallar.
.toString() sí que té una habilitat exclusiva: convertir a una altra base numèrica.
console.log((255).toString(2)); // '11111111' (binari)
console.log((255).toString(16)); // 'ff' (hexadecimal)3.3 Template literals
La manera més natural de convertir a text en el dia a dia:
Tot el que fiquis a ${} es converteix a text automàticament.
| Mètode | Segur amb null/undefined |
Llegibilitat | Ús recomanat |
|---|---|---|---|
String(valor) |
Sí | Alta | Conversió explícita general |
valor.toString() |
No | Alta | Canvi de base numèrica |
`${valor}` |
Sí | Molt alta | Compondre missatges |
valor + '' |
Sí | Baixa | Evitar |
- Conversió explícita a booleà: truthy i falsy
Quan JavaScript necessita un booleà (en un if, en un &&, en un !), converteix el que li donis. Els valors que es converteixen en false s'anomenen falsy; la resta, truthy.
4.1 La llista completa de valors falsy
Només hi ha vuit valors falsy en JavaScript. Val la pena memoritzar-los, perquè tota la resta és truthy:
| Valor falsy | Comentari |
|---|---|
false |
El booleà fals |
0 |
El zero |
-0 |
El zero negatiu |
0n |
El zero de tipus bigint |
'' |
La cadena buida (també "" i ``) |
null |
|
undefined |
|
NaN |
console.log(Boolean(false)); // false
console.log(Boolean(0)); // false
console.log(Boolean('')); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean(NaN)); // false4.2 Els truthy que més sorprenen
Com que tot el que no és a la llista és truthy, alguns casos xoquen:
console.log(Boolean('0')); // true ← el TEXT '0' és truthy!
console.log(Boolean('false')); // true ← el TEXT 'false' també
console.log(Boolean(' ')); // true ← un espai no és cadena buida
console.log(Boolean([])); // true ← un array buit és truthy!
console.log(Boolean({})); // true ← un objecte buit també
console.log(Boolean(-1)); // true ← qualsevol nombre que no sigui 0Els dos que més problemes causen a la pràctica:
'0'és truthy. Si un formulari retorna'0'hores,if (hores)es complirà.[]és truthy. Per saber si una llista d'etiquetes és buida cal miraretiquetes.length === 0, noif (!etiquetes).
const etiquetes = [];
if (etiquetes) {
console.log('Això SEMPRE es mostra, encara que la llista sigui buida');
}
if (etiquetes.length === 0) {
console.log('Així sí que es detecta una llista buida'); // ← correcte
}
- Conversió implícita (coerció)
Ara que saps convertir tu, vegem quan ho fa JavaScript pel seu compte.
5.1 Coerció a text: el +
Si algun dels operands de + és un string, l'altre es converteix a string.
console.log('Hores: ' + 12); // 'Hores: 12'
console.log(12 + ''); // '12'
console.log('12' + true); // '12true'
console.log('12' + null); // '12null'
console.log('12' + undefined); // '12undefined'
console.log('12' + [1, 2]); // '121,2'5.2 Coerció a nombre: la resta d'operadors aritmètics
-, *, /, % i ** sempre converteixen a nombre:
console.log('12' - 4); // 8
console.log('12' * '2'); // 24
console.log(true + 1); // 2 ← true es converteix en 1
console.log(false + 1); // 1 ← false es converteix en 0
console.log(null + 5); // 5 ← null es converteix en 0
console.log(undefined + 5); // NaN ← undefined es converteix en NaN
console.log([] + 1); // '1' ← l'array buit es converteix a ''
console.log([5] * 2); // 10 ← [5] es converteix a '5' i després a 5Les quatre últimes línies són el tipus de raresa que fa famós JavaScript. No les memoritzis: memoritza la conclusió, que és no barrejar tipus.
5.3 El cas que trenca càlculs reals
Aquest és l'error pràctic que et trobaràs de debò:
// Dades que arriben d'un formulari: SEMPRE són text
const horesTasca1 = '12';
const horesTasca2 = '8';
console.log(horesTasca1 + horesTasca2); // '128' ← malament!
// Convertint abans d'operar
console.log(Number(horesTasca1) + Number(horesTasca2)); // 20 ← correcteI el que passa quan només un dels valors és text:
const horesIvan = 12; // nombre
const horesLucia = '8'; // text (ve d'un input)
console.log(horesIvan + horesLucia); // '128' ← concatena
console.log(horesIvan - horesLucia); // 4 ← resta bé
console.log(horesIvan * horesLucia); // 96 ← multiplica béQue uns operadors funcionin i d'altres no és el que fa tan difícil de localitzar aquesta fallada: el programa sembla que funciona fins que arriba a una suma.
- Operadors de comparació
Els operadors relacionals retornen sempre un booleà:
| Operador | Nom | Exemple | Resultat |
|---|---|---|---|
> |
Més gran que | 12 > 8 |
true |
< |
Més petit que | 12 < 8 |
false |
>= |
Més gran o igual | 12 >= 12 |
true |
<= |
Més petit o igual | 8 <= 12 |
true |
== |
Igualtat laxa | '12' == 12 |
true |
=== |
Igualtat estricta | '12' === 12 |
false |
!= |
Desigualtat laxa | '12' != 12 |
false |
!== |
Desigualtat estricta | '12' !== 12 |
true |
const horesEstimades = 12;
const MAX_HORES_DIA = 8;
console.log(horesEstimades > MAX_HORES_DIA); // true
console.log(horesEstimades <= MAX_HORES_DIA); // false
== enfront de ===
== enfront de ===Aquí hi ha el cor de la lliçó.
===(igualtat estricta) compara valor i tipus. Si els tipus difereixen, retornafalsesense més.==(igualtat laxa) converteix els valors a un tipus comú abans de comparar.
console.log('12' === 12); // false ← tipus diferents
console.log('12' == 12); // true ← converteix '12' a 12 i compara7.1 Els casos clàssics de ==
| Comparació | == |
=== |
Per què |
|---|---|---|---|
'5' == 5 |
true |
false |
El text es converteix a nombre |
'' == 0 |
true |
false |
La cadena buida es converteix a 0 |
'0' == 0 |
true |
false |
'0' es converteix a 0 |
'' == '0' |
false |
false |
Tots dos són text: es comparen tal qual |
false == 0 |
true |
false |
false es converteix a 0 |
false == '' |
true |
false |
Tots dos es converteixen a 0 |
null == undefined |
true |
false |
Regla especial del llenguatge |
null == 0 |
false |
false |
null només és laxament igual a undefined |
NaN == NaN |
false |
false |
NaN no és mai igual a res, ni a si mateix |
[] == false |
true |
false |
[] → '' → 0, i false → 0 |
[] == '' |
true |
false |
L'array buit es converteix a cadena buida |
Fixa't en la incoherència demolidora: '' == 0 és true i '0' == 0 és true, però '' == '0' és false. És a dir, == no és transitiu. Dos valors poden ser "iguals" a un tercer i no ser-ho entre ells. Això tot sol ja hauria de bastar per desterrar == del teu codi.
7.2 L'única excepció tolerada
Hi ha un ús de == que molts equips accepten: comprovar d'un sol cop si un valor és null o undefined.
const revisor = null;
// Amb == cobreix els dos casos alhora
if (revisor == null) {
console.log('Sense revisor assignat');
}
// Equivalent estricte, més explícit
if (revisor === null || revisor === undefined) {
console.log('Sense revisor assignat');
}Tot i així, avui existeix una alternativa més neta amb ??, que ja coneixes:
7.3 El cas de NaN
NaN és l'únic valor de JavaScript que no és igual a si mateix, ni amb == ni amb ===:
Per això existeix Number.isNaN():
Compte amb la funció global antiga isNaN(), que converteix abans de comprovar i dona falsos positius:
console.log(isNaN('alta')); // true ← converteix 'alta' a NaN primer
console.log(Number.isNaN('alta')); // false ← 'alta' és un string, no NaNFes servir sempre Number.isNaN().
- Comparar cadenes i comparar nombres
Els operadors < i > es comporten de manera diferent segons els tipus.
Si tots dos són text, es comparen caràcter a caràcter segons el seu codi Unicode (aproximadament, ordre alfabètic):
console.log('alta' < 'baixa'); // true ← 'a' va abans que 'b'
console.log('Iván' < 'iván'); // true ← les majúscules van abans
console.log('10' < '9'); // true ← comparació de TEXT! '1' < '9'Aquesta última línia és un parany clàssic: com a text, '10' és més petit que '9' perquè es compara el primer caràcter.
Si algun és nombre, tots dos es converteixen a nombre:
Per ordenar textos amb criteri d'idioma (accents, dígrafs) existeix localeCompare:
8.1 Per què les dates ISO són tan còmodes
Aquí es veu per què a Nómada Tasques desem les dates com a text 'yyyy-mm-dd':
const data1 = '2026-09-30';
const data2 = '2026-11-05';
console.log(data1 < data2); // true — ordre cronològic correcteEl format ISO té la propietat que el seu ordre alfabètic coincideix amb el seu ordre cronològic, perquè els components van de més a menys magnitud i amb zeros a l'esquerra. Amb '30/09/2026' això no funcionaria de cap manera.
- Comparar objectes: el parany de la referència
Recorda de la lliçó de tipus: els objectes i arrays es manegen per referència. En comparar-los, JavaScript no mira el contingut: mira si són el mateix objecte a la memòria.
const etiquetes1 = ['disseny', 'espai'];
const etiquetes2 = ['disseny', 'espai'];
console.log(etiquetes1 === etiquetes2); // false ← contingut igual, objectes diferents
console.log(etiquetes1 == etiquetes2); // false ← == tampoc no ajuda
const etiquetes3 = etiquetes1;
console.log(etiquetes1 === etiquetes3); // true ← és el mateix objecteEl mateix amb objectes:
const tascaA = { id: 1, titol: 'Revisar factures' };
const tascaB = { id: 1, titol: 'Revisar factures' };
console.log(tascaA === tascaB); // false
console.log(tascaA.id === tascaB.id); // true ← comparant primitius, síflowchart TD
A["etiquetes1"] --> M1["Memòria: ['disseny','espai']"]
B["etiquetes2"] --> M2["Memòria: ['disseny','espai']"]
C["etiquetes3"] --> M1
M1 -.->|"=== M2"| R["false: són<br/>zones diferents"]
Regla pràctica: per comparar dues tasques, compara'n els camps (normalment l'id), mai els objectes sencers amb ===. Les tècniques per comparar continguts es veuen a JSON i Còpies d'Objectes.
Object.is i els casos límit
Object.is i els casos límitObject.is() (ES2015) es comporta com === llevat de dos casos on === té un comportament discutible:
console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true ← més raonable
console.log(0 === -0); // true
console.log(Object.is(0, -0)); // false ← distingeix el zero negatiu| Comparació | == |
=== |
Object.is |
|---|---|---|---|
'12' i 12 |
true |
false |
false |
null i undefined |
true |
false |
false |
NaN i NaN |
false |
false |
true |
0 i -0 |
true |
true |
false |
'alta' i 'alta' |
true |
true |
true |
En el dia a dia faràs servir ===. Object.is és útil quan t'importi distingir NaN o el zero negatiu, situacions poc freqüents però reals en càlculs numèrics.
- Regles pràctiques d'higiene
Cinc regles que t'estalviaran la major part dels problemes d'aquesta lliçó:
- Fes servir sempre
===i!==. Sense excepcions mentre aprens. Les eines de qualitat de codi que veuràs al Mòdul 8 t'avisaran si se t'escapa un==. - Converteix explícitament abans d'operar. Si una dada pot ser text, aplica-li
Number()abans de sumar-la. No confiïs en la coerció. - No barregis tipus en una mateixa variable. Si
horesés un nombre, que sigui sempre un nombre. - Comprova l'absència de valor explícitament.
if (valor === null)ovalor ?? defecte, en lloc de confiar en truthy/falsy. - Compte amb
0,''i[]. Els dos primers són falsy encara que siguin dades vàlides; el tercer és truthy encara que estigui buit.
flowchart TD
A["Reps una dada"] --> B{"D'on<br/>ve?"}
B -->|"Formulari, URL,<br/>emmagatzematge"| C["És TEXT,<br/>sempre"]
B -->|"El teu propi codi"| D["Ja té el<br/>tipus correcte"]
C --> E["Converteix amb<br/>Number() o String()"]
E --> F["Valida amb<br/>Number.isNaN() i trim()"]
F --> G["Compara amb ==="]
D --> G
- Aplicació: validar les dades d'un formulari de tasca
La Marta omple un formulari per donar d'alta una tasca a Nómada Tasques. Els camps d'un formulari web retornen sempre text, fins i tot els numèrics i els de data. Comprovem les dades abans de fer-les servir.
'use strict';
// --- Dades tal com arriben d'un formulari: TOT són strings ---------
const idText = '5';
const titolText = ' Preparar el taller de serigrafia ';
const responsableText = ''; // no s'ha omplert
const prioritatText = 'mitjana';
const horesText = '6';
const dataLimitText = '2026-10-15';
const etiquetesText = 'taller, formació';
// --- Conversió explícita ------------------------------------------
const id = Number(idText);
const titol = titolText.trim(); // treu els espais sobrants
const horesEstimades = Number(horesText);
// --- Validacions ---------------------------------------------------
// 1. L'id ha de ser un nombre vàlid i positiu
const idEsValid = !Number.isNaN(id) && id > 0;
// 2. El títol no pot estar buit un cop retallat
const titolEsValid = titol !== '';
// 3. Les hores: nombre vàlid, més gran que 0. Compte: Number('') és 0
const horesSonValides =
horesText.trim() !== '' && !Number.isNaN(horesEstimades) && horesEstimades > 0;
// 4. La prioritat ha de ser un dels tres valors permesos
const prioritatEsValida =
prioritatText === 'alta' ||
prioritatText === 'mitjana' ||
prioritatText === 'baixa';
// 5. La data ISO té sempre 10 caràcters i no pot ser passada
const AVUI = '2026-08-18';
const dataEsValida =
dataLimitText.length === 10 && dataLimitText >= AVUI;
// 6. El responsable pot faltar: fem servir null a propòsit
const responsable = responsableText.trim() === '' ? null : responsableText.trim();
// 7. Les etiquetes: si el text és buit, llista buida
// split(', ') parteix el text pel separador i retorna un array
const etiquetes =
etiquetesText.trim() === '' ? [] : etiquetesText.split(', ');
// --- Resultat global -----------------------------------------------
const formulariEsValid =
idEsValid && titolEsValid && horesSonValides &&
prioritatEsValida && dataEsValida;
// --- Sortida -------------------------------------------------------
console.log('=== Validació de la tasca ===');
console.log(`id (${typeof id}): ${id} → ${idEsValid ? 'OK' : 'ERROR'}`);
console.log(`títol: "${titol}" → ${titolEsValid ? 'OK' : 'ERROR'}`);
console.log(`hores (${typeof horesEstimades}): ${horesEstimades} → ${horesSonValides ? 'OK' : 'ERROR'}`);
console.log(`prioritat: ${prioritatText} → ${prioritatEsValida ? 'OK' : 'ERROR'}`);
console.log(`data límit: ${dataLimitText} → ${dataEsValida ? 'OK' : 'ERROR'}`);
console.log(`responsable: ${responsable ?? 'Sense assignar'}`);
console.log(`etiquetes (${etiquetes.length}): ${etiquetes.join(' · ')}`);
console.log(`\nFormulari vàlid: ${formulariEsValid ? 'SÍ' : 'NO'}`);Sortida:
=== Validació de la tasca === id (number): 5 → OK títol: "Preparar el taller de serigrafia" → OK hores (number): 6 → OK prioritat: mitjana → OK data límit: 2026-10-15 → OK responsable: Sense assignar etiquetes (2): taller · formació Formulari vàlid: SÍ
Decisions importants d'aquest codi:
- Tot es converteix explícitament.
Number(idText)iNumber(horesText)en lloc de confiar que el+es porti bé. .trim()abans de validar textos. Un títol de només espais passaria una comprovació ingènua.- La doble comprovació d'hores.
horesText.trim() !== ''és imprescindible perquèNumber('')retorna0, noNaN. Sense ella, un camp buit passaria com a "0 hores". ===en totes les comparacions. La prioritat es compara amb els tres valors exactes.- La data es compara com a text aprofitant el format ISO.
'2026-10-15' >= '2026-08-18'éstrue. - El responsable absent és
null, no''. Estem afirmant "no hi ha responsable", no desant un text buit. - Les etiquetes absents són
[], nonull. Una llista buida continua sent una llista, i així tot el codi posterior pot tractar-la igual.
La validació des del punt de vista de la interfície —llegir el formulari real, mostrar missatges d'error al costat de cada camp, impedir l'enviament— és matèria de Gestió i Validació de Formularis. Aquí ens hem centrat en la lògica de conversió i comparació, que és la part que de debò decideix si una dada és correcta.
Errors Habituals i Consells
Errors habituals
- Fer servir
==per costum. Genera errors que apareixen mesos després amb dades concretes. Fes servir===. - Oblidar que
Number('')és0. Un camp buit passa com a zero hores i ningú no se n'assabenta. - Confiar en
if (valor)per a nombres. Sivalorés0, la condició no es compleix encara que la dada sigui legítima. - Comprovar si un array és buit amb
if (!llista). Un array buit és truthy. Fes servirllista.length === 0. - Comparar
NaNamb===. No funciona mai. Fes servirNumber.isNaN(). - Fer servir la funció global
isNaN(). Converteix abans de comprovar i dona falsos positius. Fes servirNumber.isNaN(). - Comparar objectes o arrays amb
===esperant comparar-ne el contingut. Compara referències. Compara'n els camps. - Cridar
.toString()sobre una cosa que pot sernull.TypeErrorgarantit. Fes servirString(). - Comparar nombres desats com a text amb
<o>.'10' < '9'éstrue. Converteix abans. - Sumar directament valors d'un formulari.
'12' + '8'és'128'.
Consells
- Converteix a la frontera. Tan bon punt una dada entra al teu programa (formulari, URL, emmagatzematge), converteix-la al tipus correcte. A partir d'aquí, tot el codi hi pot confiar.
- Memoritza els vuit valors falsy. És la taula que més rendibilitat et donarà de tot el mòdul.
- Quan alguna cosa es comporti de manera estranya, imprimeix
typeof.console.log(typeof x, x)resol la meitat dels misteris en dos segons. - Dona nom a les validacions:
const horesSonValides = .... Unifamb cinc condicions sense nom és il·legible. - Fes servir dates ISO
'yyyy-mm-dd'i les podràs comparar i ordenar com a text sense cap llibreria. Number()per validar,parseInt/parseFloatper extreure.
Exercicis
Exercici 1: Prediu les conversions
Escriu el resultat de cada línia:
console.log(Number(' 25 ')); // A
console.log(Number('')); // B
console.log(Number('25 hores')); // C
console.log(parseInt('25 hores')); // D
console.log(parseFloat('7.5h')); // E
console.log(Number(null)); // F
console.log(Number(undefined)); // G
console.log(String(null)); // H
console.log(Boolean('0')); // I
console.log(Boolean([])); // J
console.log(Boolean('')); // K
console.log(Boolean(-1)); // LExercici 2: == enfront de ===
Omple la taula indicant el resultat de cada comparació amb els dos operadors, i explica els tres casos que et semblin més sorprenents:
| Comparació | == |
=== |
|---|---|---|
'6' ? 6 |
||
'' ? 0 |
||
'' ? '0' |
||
null ? undefined |
||
null ? 0 |
||
false ? 0 |
||
NaN ? NaN |
||
'alta' ? 'alta' |
Exercici 3: Validador d'hores d'una tasca
Escriu un script que validi el camp "hores estimades" d'un formulari de Nómada Tasques. Ha de comprovar, per a cada valor d'entrada, que:
- No està buit ni conté només espais.
- És un nombre vàlid.
- És més gran que
0. - No supera les
40hores (una setmana completa).
Per a cada entrada, imprimeix el valor original, el valor convertit i el resultat (OK o el motiu de l'error).
Prova amb aquestes entrades: '8', '0', '', ' ', 'vuit', '7.5', '45', '8 hores'.
Solucions
Exercici 1
| Línia | Resultat | Explicació |
|---|---|---|
| A | 25 |
Number() ignora els espais del voltant |
| B | 0 |
La cadena buida es converteix a 0, no a NaN |
| C | NaN |
Number() exigeix que tot el text sigui numèric |
| D | 25 |
parseInt llegeix des del principi i s'atura a l'espai |
| E | 7.5 |
parseFloat conserva decimals i s'atura a la h |
| F | 0 |
null es converteix numèricament a 0 |
| G | NaN |
undefined no té equivalent numèric |
| H | 'null' |
String() funciona amb null (a diferència de .toString()) |
| I | true |
El text '0' no és la cadena buida, així que és truthy |
| J | true |
Un array buit és un objecte, i tots els objectes són truthy |
| K | false |
La cadena buida és a la llista de falsy |
| L | true |
Només el 0 és falsy; qualsevol altre nombre és truthy |
Exercici 2
| Comparació | == |
=== |
|---|---|---|
'6' i 6 |
true |
false |
'' i 0 |
true |
false |
'' i '0' |
false |
false |
null i undefined |
true |
false |
null i 0 |
false |
false |
false i 0 |
true |
false |
NaN i NaN |
false |
false |
'alta' i 'alta' |
true |
true |
Els tres casos més sorprenents:
'' == 0éstrueperò'' == '0'ésfalse. Quan els dos operands són text,==no converteix res i els compara tal qual. Això demostra que==no és transitiu:''és "igual" a0i'0'és "igual" a0, però''i'0'no són iguals entre ells.null == undefinedéstrueperònull == 0ésfalse. No hi ha cap lògica de conversió al darrere: és una regla especial escrita explícitament a l'especificació.nullnomés és laxament igual aundefinedi a si mateix.NaN == NaNésfalse. L'únic valor del llenguatge que no és igual a si mateix, seguint l'estàndard IEEE 754 de coma flotant. Per això existeixNumber.isNaN().
Exercici 3
'use strict';
// --- Constants de negoci -------------------------------------------
const MIN_HORES = 0;
const MAX_HORES = 40;
// --- Entrades a provar ---------------------------------------------
const entrada = '8'; // canvia-la per provar les altres
// --- Validació pas a pas -------------------------------------------
const retallada = entrada.trim();
const hores = Number(retallada);
// Ternari encadenat: l'ordre de les comprovacions és deliberat
const resultat =
retallada === '' ? 'ERROR: el camp és buit' :
Number.isNaN(hores) ? 'ERROR: no és un nombre vàlid' :
hores <= MIN_HORES ? 'ERROR: ha de ser més gran que 0' :
hores > MAX_HORES ? `ERROR: no pot superar ${MAX_HORES} hores` :
'OK';
console.log(`"${entrada}" → ${hores} (${typeof hores}) → ${resultat}`);Resultats esperats per a totes les entrades:
| Entrada | trim() |
Number() |
Resultat |
|---|---|---|---|
'8' |
'8' |
8 |
OK |
'0' |
'0' |
0 |
ERROR: ha de ser més gran que 0 |
'' |
'' |
0 |
ERROR: el camp és buit |
' ' |
'' |
0 |
ERROR: el camp és buit |
'vuit' |
'vuit' |
NaN |
ERROR: no és un nombre vàlid |
'7.5' |
'7.5' |
7.5 |
OK |
'45' |
'45' |
45 |
ERROR: no pot superar 40 hores |
'8 hores' |
'8 hores' |
NaN |
ERROR: no és un nombre vàlid |
Tres observacions clau:
- L'ordre de les comprovacions importa. La de cadena buida va primer, perquè
Number('')dona0i aquesta entrada acabaria donant el missatge "ha de ser més gran que 0", que és confús i no descriu el problema real. ' 'i''produeixen el mateix error gràcies al.trim()previ.'8 hores'es rebutja perquè hem fet servirNumber(). Si haguéssim fet servirparseInt, hauria passat com a8en silenci. En una validació d'entrada això seria un error:Number()és l'elecció correcta per validar.
Conclusió
Has desbrossat el terreny on més s'ensopega en JavaScript. Saps convertir explícitament amb Number(), parseInt(), parseFloat(), String(), .toString() i Boolean(), i coneixes els paranys de cadascun (Number('') és 0, .toString() falla amb null). Domines la conversió implícita: el + concatena si hi ha un string, la resta d'operadors aritmètics converteixen a nombre. Et saps la llista completa dels vuit valors falsy i recordes que '0' i [] són truthy. Distingeixes == de === i has vist per què la igualtat laxa ni tan sols és transitiva. Saps que les cadenes es comparen alfabèticament —i per què això fa tan còmodes les dates ISO—, que els objectes es comparen per referència, i que existeix Object.is per als casos límit de NaN i -0.
I el més pràctic: has escrit un validador complet per a les dades d'un formulari de tasca de Nómada Tasques, aquelles que arriben sempre com a text.
Amb això tanques la caixa d'eines bàsica: entorn, sintaxi, variables, tipus, operadors i comparacions. Ja tens tot el que cal per entendre el projecte en conjunt. A l'última lliçó del mòdul, El Projecte del Curs: Nómada Tasques, coneixeràs a fons Taller Nómada i el seu problema, el model de dades canònic d'una tasca amb tots els seus camps i valors permesos, i el mapa complet del que construiràs a cada mòdul del curs.
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
