Bezero ingurunean web garapenaren sarrera
1 Sarrera
Web-orri bat erabiltzen dugunean, hainbat ekintza-programa eta zerbitzu sartzen diren ekintza-sekuentzia bat hasten da (batzuk gure ekipoan eta beste batzuk hortik kanpo). Sekuentzia sinplifikatuta honako hau izango litzateke:
- Erabiltzaileak bisitatu nahi duen web-orriaren URL bat sartzen du nabigatzailean.
- Gure ekipoak DNS eskaera bat egiten du eskaera zein IP helbidetara egin behar den jakiteko.
- Nabigatzaileak orria zerbitzariari eskatzen dio.
- Zerbitzariak eskaera prozesatzen du. Zerbitzarian hainbat prozesu egin ohi dira, hala nola:
- Eskaera jasotzea.
- Eskaera prozesatzea (programazio-lengoaia bat behar izan dezake: PHP/Ruby/Python/Java…).
- Beharrezkoa bada, datu-base batera sartzea.
- Zerbitzariak itzuli behar duen informazioa sortzea.
- Zerbitzariak informazioa itzultzen du.
- Nabigatzaileak informazio hori (HTML eta CSS kodea) interpretatu eta erabiltzaileari erakusten dio.
- Informazio horren zati bat gure nabigatzailean exekutatzen den programazio-lengoaia baten bidez sortuta egon daiteke.
- eta 5. urratsak irudiekin, CSS fitxategiekin, JS fitxategiekin, bideoekin eta abarrekin ere errepikatzen dira.
Gaur egun, lehen mahaigaineko programak ziren aplikazio askok nabigatzaile batetik soilik funtzionatzen dute:
- Posta elektronikoa
- Argazkiak ukitzeko programak
- Enpresa-kudeatzaileak (fakturak/almategia/hitzorduak)
- Jokoak
2 Web-garapenaren historia bezero-ingurunean
Gaur egun, nabigatzailean web-garapenaz pentsatzen dugunean, ohikoena HTML, CSS eta JavaScript-en pentsatzea da. Hala ere, ez da beti horrela izan. Historian zehar, teknologia desberdinak erabili dira web-orriei interaktibitatea gehitzeko. Batzuk desagertu egin ziren, eta beste batzuk eboluzionatuz joan ziren gaur egungo estandarrak bihurtu arte.
2.1 Lehen urteak: web-orri estatikoak
1991n, Tim Berners-Lee HTMLren garapenean hasi zen CERN erakundean. HTML lengoaia sortzeaz gain, HTTP (HyperText Transfer Protocol) protokoloa eta lehen web-zerbitzaria ere sortu zituen.
1993an argitaratu eta estandar gisa proposatu zuen IETF erakundeak. Une horretan, web-orriak HTML-z soilik osatuta zeuden. Haien edukia guztiz estatikoa zen: testua, irudiak eta estekak erakusten zituzten, baina ia ez zegoen erabiltzailearekiko interakziorik.
Ondoren, 1996an, CSS agertu zen. Horri esker, edukia aurkezpenetik bereizi eta web-orrien itxura bisuala hobetu ahal izan zen.
Garai hartan, edozein prozesamendu konplexu zerbitzarian egin behar zen, nabigatzaileak exekuzio-gaitasun oso mugatua baitzuen.
2.1.1 Zerbitzari-inguruneko lengoaiak
Irakasgai honetan bezero-ingurunean zentratuko bagara ere, interesgarria da jakitea lehen urte haietan, web-orriak backend-ean programatuz sortu ahal izateko, garai hartan UNIX inguruneetan ohikoenak ziren lengoaiak erabiltzen zirela, hala nola C, Perl eta, ondoren, Python.
Programazio-lengoaia horiek erabiltzeko, CGI (Common Gateway Interface) interfazea erabiltzen zen. Interfaze horrek web-zerbitzariei eskaera HTTP prozesatzen zuen kanpoko programa bat exekutatzea ahalbidetzen zien.
Prozesuak honela funtzionatzen zuen HTTP eskaera bakoitzerako:
- Prozesu berri bat sortzea.
- Programa kargatzea.
- Exekutatzea.
- Prozesua amaitzea.
Horren ondorioz, CPU eta memoria-baliabide asko kontsumitzen zituen.
CGI erabiltzen hasi zen aplikazio-zerbitzariak edo web-zerbitzarietako moduluak agertu aurretik.
2.2 JavaScript: orri dinamikoen jaiotza
1995ean, Netscape enpresak JavaScript garatu zuen, web-orriei funtzionalitate txikiak gehitzeko helburuarekin, zerbitzariarekin etengabe komunikatu beharrik gabe.
JavaScript-i esker, honako hauek egin ahal izan ziren:
- Inprimakiak bidali aurretik baliozkotzea.
- Orriko elementuak erakustea edo ezkutatzea.
- Menu interaktiboak sortzea.
- Erabiltzailearen ekintzei berehala erantzutea.
Urteek aurrera egin ahala, JavaScript eboluzionatuz joan zen programazio-lengoaia oso ahaltsua bihurtu arte, web-aplikazio osoak garatzeko gai izanik.
Gaur egun, nabigatzaile guztiek natiboki exekutatzen duten programazio-lengoaia bakarra da.
Netscapek bere web-nabigatzailearen kodea askatu zuen eta Mozilla erakundea sortu zuen; erakunde horrek, aldi berean, nabigatzailea berridatzi zuen, eta geroago Firefox bihurtuko zen.
2.3 Java Applets: Java aplikazioak nabigatzailean
Handik gutxira, oso ezaguna egin zen beste teknologia bat agertu zen: Java Applets. Applet bat Java-n idatzitako programa bat zen, web-orri batetik deskargatu eta erabiltzailearen ordenagailuan exekutatzen zena, nabigatzailearen plugin gisa instalatutako Java Makina Birtualaren (JVM) bidez.
Applet-ek garai hartako JavaScript-ekin egin zitezkeenak baino aplikazio askoz konplexuagoak garatzeko aukera ematen zuten. Adibidez:
- Jokoak.
- Simulazioak.
- Marrazketa-tresnak.
- Hezkuntza-aplikazioak.
- Hiru dimentsioko bistaratzaileak.
Hala ere, hainbat eragozpen zituzten:
- Beharrezkoa zen ordenagailuan Java instalatzea.
- Nabigatzailearen plugin baten mende zeuden.
- Kargatzeko denbora luzea behar zuten.
- Segurtasun-arazo ugari zituzten.
2017an zaharkitutzat jo zen, eta nabigatzaileek Applet-ak exekutatzeko beharrezkoak ziren pluginak onartzeari utzi zioten.
2.4 Adobe Flash: Interneteko animazioak
90eko hamarkadaren amaieran eta 2000ko hamarkadaren zati handi batean, Adobe Flash Interneten multimedia-edukiak sortzeko teknologia nagusietako bat bihurtu zen. Flash-ek honako hauek garatzeko aukera ematen zuen:
- Animazioak.
- Jokoak.
- Bideo-erreproduzitzaileak.
- Publizitate interaktiboa.
- Aplikazio osoak.
Urte askotan oso erabilia izan zen, nabigatzaileek oraindik ez baitzituzten gaitasun horietako asko natiboki eskaintzen. Hala ere, Flash-ek hainbat arazo zituen:
- Plugin bat instalatzea eskatzen zuen.
- Baliabide asko kontsumitzen zituen.
- Segurtasun-ahultasun ugari zituen.
- Ez zuen behar bezala funtzionatzen gailu mugikor gehienetan.
2010ean, Steve Jobsek Flash-i buruzko hausnarketak izeneko gutun irekia idatzi zuen, eta bertan azaldu zuen zergatik ez zuen Applek Flash iPhone-etan erabiltzea baimentzen. Hasieran kritika ugari izan ziren, eta Appleren aurka argudiatu zitezkeen hainbat arrazoi baziren ere, urte batzuk geroago baieztatu zen Flash-ek baliabide eta bateria asko kontsumitzen zituela eta ez zela segurua.
2020an, Adobek Flash-i laguntza emateari utzi zion, eta nabigatzaileek haren bateragarritasuna erabat ezabatu zuten.
2.5 AJAX: aplikazio azkarragoak
1999an, Microsoft-ek AJAX (Asynchronous JavaScript and XML) izeneko teknika sortu zuen, 1996ko iframe etiketekiko bilakaera gisa; hasiera batean, Internet Explorer 5.0-ra mugatuta zegoen.
AJAXen aurretik, erabiltzaileak ekintza bat egiten zuen bakoitzean beharrezkoa zen orrialde osoa berriro kargatzea. AJAX-i esker, nabigatzailea zerbitzariarekin komunikatu zitekeen atzeko planoan, eta orrialdearen zati bakarra eguneratu. Horri esker, aplikazio askoz azkarragoak eta erabiltzaile-esperientzia hobea zutenak sortu ahal izan ziren.
Jatorriz datuak trukatzeko XML erabiltzen bazuen ere, gaur egun aplikazio gehienek JSON formatua erabiltzen dute.
2.6 jQuery: web-garapena sinplifikatuz
2006tik aurrera, jQuery JavaScript liburutegi ezagunenetako bat bihurtu zen. Garai hartan, JavaScript hutsez web-aplikazioak garatzea zaila zen, nabigatzaile bakoitzak DOMa eta gertaerak modu apur bat desberdinean inplementatzen baitzituen. Gainera, gaur egun ohikotzat jotzen ditugun funtzionalitate asko, hala nola querySelector(), fetch() edo gertaeren kudeaketa bateratua, oraindik ez zeuden existitzen edo ez zeuden erabilgarri nabigatzaile guztietan.
jQuery-ren helburu nagusia nabigatzaile guztiekin bateragarria zen API sinple bat eskaintzea zen. Horri esker, garatzaileek CSSren antzeko hautatzaileak erabiliz elementuak hauta zitzaketen, orrialde baten edukia alda zezaketen, gertaerak kudea zitzaketen, animazioak sor zitzaketen edo AJAX eskaerak egin zitzaketen, nabigatzaileen arteko desberdintasunez kezkatu beharrik gabe. Horrek beharrezkoa zen kode kopurua nabarmen murrizten zuen eta web-aplikazioen garapena errazten zuen.
Hainbat urtez, jQuery Interneteko webgune gehienetan egon zen, eta frontend garatzaileentzat ia ezinbesteko tresna bihurtu zen. Haren arrakasta hain handia izan zen, ezen popularizatu zituen funtzionalitate asko JavaScript-en eta nabigatzaile modernoetan natiboki txertatu baitziren azkenean.
Popularizatu zituen funtzionalitate asko JavaScript-en eta nabigatzaile modernoetan natiboki txertatu ziren azkenean.
HTML5 agertzearekin, nabigatzailearen APIak estandarizatzearekin eta Angular, React eta Vue.js bezalako frameworken garapenarekin, jQuery erabiltzeko beharra gutxituz joan zen. Gaur egun oraindik badago antzinako proiektu batzuetan, baina web-aplikazio berrietan askoz gutxiago erabiltzen da, nabigatzaile modernoek eta egungo frameworkek irtenbide osatuagoak eta ahaltsuagoak eskaintzen baitituzte.
jQuery ezagunenetako bat izan bazen ere, urte haietan baziren JavaScript zabaltzen saiatzen ziren beste liburutegi batzuk ere:
- Prototype, 2005ekoa, oso erabilia Ruby on Rails-ekin batera. DOMari metodoak gehitzen zizkion eta JavaScript sinplifikatzen zuen.
- script.aculo.us, Protoype-ren gainean sortua, animazioak, efektu bisualak eta drag & drop sortzeko liburutegia zen.
- Ext JS: mahaigaineko programen oso antzeko interfazeak dituzten enpresa-aplikazioetara bideratuta. Oraindik existitzen da, nahiz eta erabilera askoz txikiagoa izan.
2.7 HTML5: nabigatzaileak gaitasunak irabazten ditu
2007an HTML5 lehen zirriborroa argitaratu zen, HTML lengoaiaren bilakaera garrantzitsua. HTML5ek aurretik Flash bezalako kanpoko teknologien bidez soilik lor zitezkeen funtzionalitate ugari txertatu zituen.
HTML5-i esker, nabigatzaile modernoak garapen-plataforma askoz osatuago bihurtzen hasi ziren, hainbat baliabide natiboki exekutatzeko APIak txertatu baitzituzten:
- Bideoa eta audioa pluginik gabe erreproduzitzea (YouTube erabiltzen hasi zen iPhone-rako erreproduzitzaile gisa).
- Marrazkiak egitea <canvas> etiketaren bidez.
- Grafiko bektorialak SVG-rekin.
- Datuak lokalean biltegiratzea.
- Geokokapena.
- Gailuaren hainbat baliabidetara sartzeko APIak.
2.8 JavaScript frameworkak
Web-aplikazioak tamainaz handitzen joan ahala, kode guztia JavaScript erabiliz soilik garatzea gero eta zailagoa zen. Horregatik, framework desberdinak agertu ziren, aplikazio konplexuen garapena errazteko helburuarekin.
Ezagunenetako batzuk hauek dira:
Framework horiei esker, kodea antolatu, osagaiak berrerabili eta tamaina handiko aplikazioak errazago gara daitezke.
Gaur egun TypeScript ere badago. Goi-mailako programazio-lengoaia bat da, JavaScript-era transpilatzen dena. JavaScript-en superset bat da. Gaur egun hainbat framework eta aplikaziok erabiltzen dute. TypeScript kodea ez da bezero-ingurunean exekutatzen.
2.9 WebAssembly: bitarren exekuzioa nabigatzailean
Azken urteotan, WebAssembly (Wasm) izeneko teknologia berri bat agertu da. WebAssembly ez da programazio-lengoaia bat, baizik eta nabigatzaileek oso modu eraginkorrean exekuta dezaketen formatu bitar bat. C, C++, Rust eta Java bezalako programazio-lengoaiak erabiltzea ahalbidetzen du. Lengoaiok konpilatu egiten dira, aplikazioak garatzeko eta ondoren nabigatzailearen barruan exekutatzeko.
Teknologia hau bereziki erabilgarria da errendimendu handia behar duten aplikazioetarako, hala nola:
- Bideo-jokoak.
- Irudi-editoreak.
- 3D modelaketa.
- Simulazio zientifikoak.
- Bideo-edizioa.
WebAssembly-k konpilatutako kodea oso azkar exekuta dezakeen arren, JavaScript beharrezkoa izaten jarraitzen du nabigatzailearekin eta web-orriarekin elkarreragiteko.
3 Bezero-zerbitzari arkitektura
Web-aplikazio gehienek bezero-zerbitzari izeneko arkitektura erabiltzen dute. Argi bereizitako bi zatiz osatuta dago.
Hurrengo taulan bezero-ingurunearen eta zerbitzari-ingurunearen artean dauden desberdintasunen laburpena ikus daiteke:
| Bezeroa | Zerbitzaria | |
|---|---|---|
| Izan daiteke | ● Ordenagailua / mugikorra / tableta … ● Web nabigatzailea |
● Urruneko zerbitzaria |
| Funtzioa | ● Informazioa eskatu. ● Interfazea kudeatu. ● Bezero-kodea exekutatu. ● Erabiltzailearen ekintzak jaso. ● “Erabiltzaile bakar batek erabiltzen du” |
● Eskaerak jaso. ● Negozio-logika kudeatu. ● Datu-baseetara sartu. ● Erantzunak bezeroari bidali. ● Milaka erabiltzaileri erantzun diezaieke. |
| Teknologiak | ● HTML ● CSS ● Javascript ● WebAssembly (Wasm) |
● PHP ● Python ● Ruby on Rails ● Java ● NodeJS |
Hurrengo irudian arkitekturaren sinplifikazio bat ikus daiteke:
Irudian honako hauek bereiz ditzakegu:
- Bezeroa: gure ekipoak eta erabiltzen dugun Web nabigatzaileak osatzen dute.
- Zerbitzaria: web-aplikazio moderno batek honako osagai hauek izan ohi ditu:
- Web zerbitzaria: Apache HTTP Server edo Nginx, bi adibide ezagun aipatzearren.
- Zerbitzari-inguruneko programazio-lengoaia / framework
- Datu-basea: datu-base erlazionalen artean ezagunenak hauek dira: MySQL, MariaDB edo PostgreSQL.
3.1 Bezero-aldeko teknologiak
Aurretik ikusi dugun bezala, gaur egun bezero-ingurunean erabiltzen diren oinarrizko hiru teknologia daude:
- HTML: orri baten egitura definitzen du.
- CSS: itxura bisuala definitzen du.
- JavaScript: Web nabigatzailean modu natiboan exekutatzen den programazio-lengoaia da. Portaera gehitzen du, itxura bisuala modu interaktiboan aldatzea ahalbidetzen du, eskaerak zerbitzariari modu asinkronoan egin diezazkioke, …
Aurrerago, teknologia horietan sakonduko dugu.
5 Garatzeko tresnak
Ikasturtean zehar hainbat tresna erabiliko baditugu ere, ikasturtearen hasieran gutxi batzuk baino ez ditugu erabiliko. Hasteko, honako hauek erabiliko ditugu:
- Editorea: Visual Studio Code (gomendatutako luzapenak: ESLint, Prettier, Live Server).
- Git bertsioak kontrolatzeko sistema gisa.
- GitHub urruneko biltegi gisa.
- Web nabigatzailea: Firefox, Chrome, …
- Garapen-tresnak: Nabigatzaile guztiek garapena errazteko tresnak dituzte. Normalean F12 edo Ctrl + Shift + I sakatuz irekitzen dira.
JavaScript-era sarrera
6 JavaScript-en historia
Gaur egun, JavaScript web-aplikazioak garatzeko gehien erabiltzen den programazio-lengoaia da. Interneteko ia orri guztietan dago presente, eta Web nabigatzaileetan ez ezik, zerbitzarietan eta beste ingurune batzuetan ere exekuta daiteke.
1995ean Netscape enpresak sortu zuen JavaScript, baina ez zen aplikazio konplexuak garatzeko helburuarekin sortu. Hasierako helburua askoz apalagoa zen: HTML orri estatikoetan funtzionalitate txikiak gehitzea.
Denborarekin, lengoaia eboluzionatuz joan da, eta gaur egun web-aplikazioak, mahaigaineko aplikazioak, mugikorretarako aplikazioak eta baita zerbitzarietarako programak ere garatzeko plataforma osoa bihurtu da.
JavaScript izena arrazoi komertzialengatik aukeratu zen batez ere, garai hartan Javak hartzen ari zen ospe izugarria aprobetxatuz. Izena gorabehera, JavaScript eta Java guztiz desberdinak diren lengoaiak dira. Azaleko sintaxi antzekoa partekatzen dute, baina helburu, ezaugarri eta exekuzio-modu desberdinak dituzte.
90eko hamarkadaren bigarren erdian, nabigatzaileen gerra izenez ezagutzen dena hasi zen. Fabrikatzaile bakoitzak JavaScript-en ezaugarri berriak gehitzen zituen, estandar komun bati jarraitu gabe. Horren ondorioz:
- Programa bera nabigatzaile batean funtziona zitekeen eta beste batean huts egin.
- Garatzaileek nabigatzaile bakoitzerako berariazko kodea idatzi behar zuten.
- Aplikazioen mantentzea konplexua zen.
Egoera horrek agerian utzi zuen estandar bat sortzeko beharra.
6.1 Lengoaiaren estandarizazioa
1997an, ECMA International erakundeak lengoaiaren lehen zehaztapen ofiziala argitaratu zuen, eta ECMAScript izena eman zion. Une horretatik aurrera, nabigatzaileak estandar bera inplementatzen hasi ziren, eta pixkanaka haien arteko desberdintasunak murriztuz joan ziren. Gaur egun, nabigatzaile moderno guztiek ECMAScript-ek argitaratutako zehaztapenak inplementatzen dituzte.
7 ECMAScript
JavaScript-i buruz hitz egiten dugunean, ohikoa da JavaScript eta ECMAScript terminoak bereizi gabe erabiltzea. Hala ere, ez dute zehazki gauza bera esan nahi.
- ECMAScript lengoaia nola funtzionatu behar duen definitzen duen zehaztapena edo estandarra da. Zehaztapena hemen irakur daiteke: ECMAScript® 2026 Language Specification.
- JavaScript estandar horren inplementazioa da, exekuzio-motor desberdinek egina.
Web nabigatzaile bat erabiltzen dugunean, inplementatuta duen exekuzio-motorra (JavaScript Engine) erabiliko dugu:
- SpiderMonkey: Mozillaren fundazioak sortua eta Firefoxek eta haren deribatuek erabiltzen dutena; MongoDB eta GNOME mahaigaineko ingurunean ere erabiltzen da.
- V8: Googlek 2008an sortua, Chrome-n erabiltzeko. Zerbitzari-ingurunean ere erabiltzen da, batez ere Node.js eta [Electron](https://en.wikipedia.org/wiki/Electron_(software_framework)] oinarri duten aplikazioetan.
- JavaScriptCore: Safari-k erabiltzen duena.
ECMAren barruan TC39 izeneko batzorde bat dago, lengoaiaren ezaugarri berriak aztertzeaz, diseinatzeaz eta onartzeaz arduratzen dena. Haren eginkizun nagusien artean hauek daude:
- Funtzionalitate berriak proposatzea.
- Haien bideragarritasuna aztertzea.
- Hobekuntza posibleak eztabaidatzea.
- Estandarraren aldaketak onartzea.
Helburua JavaScript modu ordenatuan eta aurreko bertsioekin bateragarria izanik eboluzionatzea bermatzea da.
7.1 Eboluzioa
2009an ECMAScript 5 (ES5) izeneko lengoaiaren bertsio berri bat agertu zen. Bertsio horrek nabigatzaileen arteko egonkortasuna eta bateragarritasuna nabarmen hobetu zituen. Hala ere, aldaketarik garrantzitsuena 2015ean iritsi zen, ECMAScript 2015 (ES6) argitaratu zenean, horrek lengoaia eraldatu baitzuen.
2015etik aurrera, urtero argitaratzen dira estandarraren bertsio berriak, hobekuntza txikiak eta funtzionalitate berriak gehituz. Wikipedian bertsioen historia ikus daiteke.
7.2 Denbora-lerroa
| Urtea | Gertaera |
|---|---|
| 1991 | World Wide Web-a sortu zen. |
| 1995 | Brendan Eich-ek JavaScript sortu zuen Netscape Navigator-erako. |
| 1997 | ECMAScript-en lehen zehaztapena argitaratu zen. |
| 1999 | ECMAScript 3 hainbat urtez estandar nagusi bihurtu zen. |
| 2005 | AJAX ezagun egin zen eta web-aplikazio dinamikoagoak agertzen hasi ziren. |
| 2006 | jQuery-k JavaScript-en garapena sinplifikatu zuen. |
| 2009 | ECMAScript 5 argitaratu zen. Objektuetan hobekuntzak, modu “zorrotza”, JSONen hobekuntzak, … |
| 2015 | ECMAScript 2015 (ES6) bertsioak lengoaiaren modernizazio sakona ekarri zuen. let eta const aldagaiak, klaseak, moduluak, promesak, lehenetsitako parametroak… |
| 2016-Gaur egun | ECMAScript-en bertsio berriak urtero argitaratzen dira. |
7.3 Nabigatzaileen arteko bateragarritasuna
Lengoaiaren bilakaera dela eta, exekuzio-motorrek eta nabigatzaileek ez dute zertan beti azken bertsioa erabili, edo baliteke funtzionalitate berriei lehentasun desberdinak ematea. Nabigatzaileen bateragarritasunak kontsultatzeko, honako webgune hauek erabil ditzakegu:
- Mozilla Developer Network: Garatzaileek gehien erabiltzen duten dokumentazio ofiziala.
- ECMAScript Compatibility Table: JavaScript lengoaiaren ezaugarrien bateragarritasuna kontsultatzeko.
- Can I use: HTML, CSS, nabigatzailearen APIak, … kontsultatzeko.
8 JavaScript-en ezaugarriak
JavaScript interpretatutako lengoaia da. Horrek esan nahi du iturburu-kodea ez dela aurrez konpilatu behar exekutatu ahal izateko. Nabigatzaileak web-orri bat kargatzen duenean, JavaScript kodea interpretatu eta exekutatzen du.
Gaur egun, JavaScript-en motor modernoek askoz teknika aurreratuagoak erabiltzen dituzte, hala nola Just-In-Time (JIT) konpilazioa. Teknika horren bidez, kodearen zati bat makina-lengoaiara itzultzen da programa exekutatzen ari den bitartean, errendimendua hobetzeko.
JavaScript-en abantaila handienetako bat da sistema eragile desberdinetan kodea aldatu gabe exekuta daitekeela, betiere sistema eragilean JavaScript motor bat badago.
JavaScript tipatze dinamikoko lengoaia da. Horrek esan nahi du aldagai batek datu-mota desberdinak gorde ditzakeela programaren exekuzioan zehar. Gainera, tipatze ahulekoa da, lengoaiak berak datu-mota desberdinen arteko bihurketa automatikoak egiten baititu beharrezkotzat jotzen duenean. Bihurketa automatiko horiek eragiketa batzuk errazten dituzte, baina emaitza ustekabeak ere sor ditzakete kontuz ibiltzen ez bada.
Beharrezkoa denean bihurketa esplizituak egitea gomendatzen da.
Programak objektuetara bideratutako programazioa erabiliz garatzea ahalbidetzen du, nahiz eta beste lengoaia batzuetatik, hala nola Java edo C#, desberdin inplementatzen den.
Ezaugarri interesgarri bat da funtzioak beste edozein balio bezala tratatzen direla. Horri esker:
- Aldagaietan gorde daitezke.
- Parametro gisa bidal daitezke.
- Beste funtzio batzuetatik itzul daitezke.
- Objektuen parte izan daitezke.
Ezaugarri hori funtsezkoa da gertaerak, tenporizadoreak edo programazio asinkronoa bezalako kontzeptuak ulertzeko.
Interpretatutako beste lengoaia batzuek bezala, memoriaren birziklapen automatikoa (Garbage Collector) egiteko sistema bat dauka. Programatzaileak ez du eskuz askatu behar jada beharrezkoak ez diren objektuek erabiltzen duten memoria. JavaScript motorrak automatikoki detektatzen du zer baliabide ez diren erabiltzen ari eta askatu egiten ditu. Horrek nabarmen murrizten du memoria-kudeaketarekin lotutako akatsak sortzeko aukera.
JavaScript modernoaren ezaugarri garrantzitsuenetako bat modu asinkronoan lan egiteko gaitasuna da. Horri esker, zeregin jakin batzuk exekuta daitezke programaren gainerakoa blokeatu gabe. Adibidez:
- Internetetik datuak deskargatzea.
- Zerbitzari baten erantzunaren zain egotea.
- Fitxategiak irakurtzea.
- Tenporizadoreak exekutatzea.
Horri esker, web-aplikazioek erabiltzailearen ekintzei erantzuten jarrai dezakete beste eragiketa batzuk amaitu bitartean.
8.1 Segurtasuna eta mugak
JavaScript erabiltzailearen nabigatzailean exekutatzeko diseinatu zen; beraz, erabiltzailearen ordenagailuan edo gailuan exekutatzen da, eta ez zerbitzarian. Ezaugarri horrek zenbait abantaila eskaintzen ditu, hala nola interaktibitate handiagoa eta aplikazioen erantzun azkarragoa. Hala ere, segurtasunarekin lotutako erronka garrantzitsuak ere sortzen ditu.
Nabigatzaile modernoek neurriak ezartzen dituzte web-orri batek erabiltzailearen ordenagailura askatasunez sartzea edo irekita dauden beste orri batzuekin interferitzea eragozteko.
8.2 Ingurune isolatua (Sandbox)
Segurtasun-neurri nagusietako bat JavaScript kodea ingurune isolatu baten barruan exekutatzea da, sandbox (hareatokia) izenez ezagutzen dena. Sandbox-ak JavaScript programa batek egin ditzakeen ekintzak mugatzen ditu, sistema eragilera zuzenean sartzea eragotziz. Mekanismo horri esker, web-orri batek ezin du, adibidez:
- Disko gogorreko edozein fitxategi irakurri.
- Sistemako fitxategiak aldatu.
- Programak instalatu.
- Sistema eragilearen aplikazioak exekutatu.
- Beste aplikazio batzuen informaziora askatasunez sartu.
- Hardwarea zuzenean atzitu. Baliabideetara (kamera, mikrofonoa, kokapena, …) sartu aurretik, erabiltzaileari baimena eskatuko dio.
Murrizketa horiek erabiltzailea web-orri maltzur posibleetatik babesten dute.
8.3 Jatorri bereko politika (Same-Origin Policy)
Segurtasun-neurri oso garrantzitsu bat Jatorri bereko politika (Same-Origin Policy) da. Politika horrek web-orri batek beste gune bateko beste web-orri baten informazioa askatasunez atzitzea eragozten du. Erabiltzaileak aldi berean bi web-orri desberdin irekita baditu, horietako bateko kodeak ezin izango du bestearen edukira sartu.
8.4 HTTP eskaeren murrizketak
Web-aplikazioak zerbitzariekin komunikatzen dira normalean HTTP eskaeren bidez. Hala ere, nabigatzaileek komunikazio horiei ere murrizketak ezartzen dizkiete. Aplikazio bat orria zerbitzatu duenaz bestelako zerbitzari batera sartzen saiatzen denean, urruneko zerbitzariak berariaz baimendu behar du komunikazio hori, CORS (Cross-Origin Resource Sharing) izeneko teknika baten bidez.
Zerbitzaria sarbidea baimentzeko konfiguratuta ez badago, nabigatzaileak eskaera blokeatuko du. Neurri horrek web-orri maltzurrek web-zerbitzuetara baimenik gabe sartzea eragozten du.
8.5 JavaScript kodea ikusgai dago
Zerbitzarian erabiltzen diren beste lengoaia batzuek ez bezala, JavaScript kodea erabiltzailearen nabigatzailera iristen da. Edonork ikus dezake nabigatzailearen garapen-tresnak erabiliz, eta, beraz, baita aldatu ere. Horregatik:
- Ez dira pasahitzak sartu behar.
- Ez dira gako pribatuak gorde behar.
- Ez dira isilpeko datuak txertatu behar.
- Ez dira segurtasun-mekanismoak JavaScript kodean soilik oinarrituta inplementatu behar.
Nabigatzailera bidalitako kode guztia publikotzat hartu behar da, nahiz eta kodea lausotzeko (obfuscation) tresnak egon.
8.5.1 Balidazioa zerbitzarian ere egin behar da
Aplikazio batek JavaScript erabil dezake formulario bat behar bezala bete den egiaztatzeko: posta elektronikoa balidatzea, eremu bat beteta dagoela ziurtatzea, …
Aurreko puntua kontuan hartuta, egiaztapen horiek ez dira nahikoak, erabiltzaileak JavaScript desgaitu, kodea bera aldatu edo zerbitzariari egindako eskaerak aldatu baititzake. Horregatik, balidazio garrantzitsu guztiak beti errepikatu behar dira zerbitzarian.
Balidazio garrantzitsu guztiak beti errepikatu behar dira zerbitzarian.
JavaScript-en egindako balidazioak erabiltzailearen esperientzia hobetzen du, baina ez du inoiz zerbitzari-aldeko balidazioa ordezkatu behar.
JavaScript-en egindako balidazioak erabiltzailearen esperientzia hobetzen du, baina ez du inoiz zerbitzari-aldeko balidazioa ordezkatu behar.
JavaScript oinarriak
9 JavaScript kodea idaztea
JavaScript web-orri batean hainbat modutan txerta daiteke. Bata edo bestea aukeratzea proiektuaren tamainaren, kodearen antolaketaren eta aplikazioaren beharren araberakoa izango da. Atal honetan JavaScript kodea HTML dokumentu batean txertatzeko modu desberdinak eta web-garapen modernoan gomendatzen diren jardunbide egokiak ikasiko ditugu.
JavaScript web-orri batean txertatzeko bi modu nagusi daude:
- Kode integratua (barnekoa).
- Kodea kanpoko fitxategi batean.
9.1 Kode integratua
Kode integratua JavaScript kodea zuzenean HTML dokumentuaren barruan idaztean datza, <script> etiketa erabiliz.
HTMLn txertatutako JavaScript kodea
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Mi primera página</title>
</head>
<body>
<h1>Hola Mundo</h1>
<!-- esto es un comentario HTML -->
<script>
// esto es un comentario en JavaScript
console.log("Hola desde JavaScript");
</script>
</body>
</html>
Nabigatzaileak <script> etiketa aurkitzen duenean, haren barruan dagoen kodea interpretatu eta berehala exekutatzen du. Web-orri berean hainbat etiketa egon daitezke, eta agertzen diren ordenan exekutatuko dira.
<script> etiketak type atributua izan dezake, hala nola type="text/javascript". Jartzen ez bada, lehenetsitako kodea JavaScript dela ulertzen da.
9.2 Kodea kanpoko fitxategi batean
JavaScript kodea idazteko modurik ohikoena .js luzapena duen fitxategi independente batean egitea da; adibidez, js/app.js. HTML fitxategitik JavaScript fitxategiari erreferentzia egiten zaio.
index.html kodea
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Mi primera página</title>
</head>
<body>
<h1>Hola Mundo</h1>
<script src="js/app.js"></script>
</body>
</html>
js/app.js kodea
console.log("Hola desde un fichero externo");
Nabigatzaileak HTML kodea jasotzen duenean, aztertu egingo du eta src atributua ikusiko du; beraz, beste eskaera bat egingo dio zerbitzariari fitxategia deskargatzeko eta, horrela, exekutatu ahal izateko. Aukera hori ia edozein proiektutan gomendatzen da, kode integratuak ez dituen hainbat abantaila baititu:
- HTML kodea garbiagoa da.
- Egitura eta logika bereizten dira.
- Fitxategi bera hainbat orritan berrerabil daiteke.
- Errazagoa da akatsak aurkitzea.
- Talde-lana errazten du.
- Nabigatzaileak fitxategia cachean gorde dezake etorkizuneko bisitetarako. Ez dio berriro zerbitzariari eskatuko.
Proiektu bat handitzen denean, komenigarria izan daiteke kodea hainbat fitxategitan banatzea.
Idatzi aurreko kodea eta bilatu non agertzen den log-a.
9.2.1 Hainbat fitxategiren karga
Orri batek JavaScript hainbat fitxategi dituenean, fitxategiak kargatzeko ordena oso garrantzitsua izan daiteke. Nabigatzaileak scriptak HTML dokumentuan agertzen diren ordenari jarraituz exekutatzen ditu. Hori kontuan hartuta, garrantzitsua da fitxategien artean mendekotasunik dagoen kontuan hartzea.
Demagun honako bi fitxategi hauek:
js/funciones.js kodea
function saludar(nombre) {
console.log(`Hola ${nombre}`);
}
js/app.js kodea
saludar("Bob");
9.3 Non kargatu JavaScript?
Tradizionalki, bi aukera zeuden.
- []{verbatim} elementuaren barruan: Metodo honek arazoak sor ditzake. Nabigatzaileak fitxategia deskargatzen duen bitartean, HTML orria eraikitzeari uzten dio. Ondorioz, erabiltzaileak karga motelagoa dela hauteman dezake, eta exekuzioren bat egiten bada, HTMLa oraindik eraiki gabe dagoenez, akatsak gerta daitezke.
- []{verbatim} elementua itxi aurretik: Urte askotan gomendioa scriptak []{verbatim} elementuaren itxieraren aurretik jartzea izan zen.
head-en kodea
<head>
<script src="03.js"></script>
</head>
<body>
<h1 id="titulo">Título</h1>
body itxi aurretik
<body>
<h1 id="titulo">Título</h1>
...
<script src="03.js"></script>
</body>
Zein desberdintasun dago hurrengo kodea head elementuan edo body elementuaren amaieran kargatzean?
console.log(document.getElementById("titulo"))
9.3.1 defer atributua
Gaur egun, gomendatzen den jardunbiderik erabiliena defer atributua erabiltzea da. Horrek errendimendua hobetzen du eta oraindik existitzen ez diren HTML elementuekin lotutako akats asko saihesten ditu, izan ere:
- nabigatzaileak HTML dokumentua eraikitzen jarraitzen du;
- JavaScript fitxategia atzeko planoan deskargatzen da;
- kodea ez da exekutatzen HTML dokumentua kargatzen amaitu arte.
Erabili “defer” atributu bezala
<head>
<script src="app.js" defer></script>
</head>
Aldatu aurreko ariketa defer erabiliz head elementuan.
9.3.2 async atributua
async atributua ere badago. Kasu honetan, nabigatzaileak fitxategia paraleloan deskargatzen du, baina deskarga amaitu bezain laster exekutatzen du, nahiz eta HTML dokumentua oraindik guztiz kargatu ez. async duten hainbat script-en arteko exekuzio-ordena ez dago bermatuta.
Horregatik, normalean script independenteetarako soilik erabiltzen da; adibidez:
- Bisiten analisi-tresnak: aplikaziotik isolatuta funtzionatzen duten liburutegiak izan ohi dira. Datuak bildu eta kanpoko zerbitzarietara bidaltzen dituzte (adibidez, Google Analytics).
- Publizitatea: aurreko kasuaren antzekoa da, baina publizitatea txertatzeko. Kasu honetan, kanpoko zerbitzari batetik datuak eskuratzen dituzte irudiak web-orrian txertatzeko.
Ez da gomendagarria async erabiltzea elkarren mendekoak diren scriptetarako.
9.4 Konparaketa eta jardunbide egokiak
Ikusi ahal izan dugun bezala, JavaScript kodea kargatzeko hainbat modu daude. Horregatik, garrantzitsua da kodea non jarri behar dugun ulertzea eta fitxategiak kargatzean atributuak erabiltzea beharrezkoa izan daitekeela jakitea.
Hurrengo irudian kargatzeko metodo desberdinen irudikapen bisuala ikus daiteke:
Hurrengo taulan ere laburbiltzen da nola erabil daitezkeen.
| Metodoa | HTMLaren karga blokeatzen du? | Ordena errespetatzen du? | Gomendatutako erabilera |
|---|---|---|---|
| <script> klasikoa | Bai | Bai | Adibide sinpleetarako soilik. |
| <script defer> | Ez | Bai | Gomendatutako aukera. |
| <script async> | Ez | Ez nahitaez | Script independenteak. |
Garrantzitsua da gure kodea kargatzeko moduen arteko desberdintasunak ezagutzea.
9.5 Lengoaiaren gramatika
Programazio-lengoaia guztiek bezala, JavaScript-ek bere gramatika eta lexikoa ditu. MDNren dokumentazioan lexiko osoa azaltzen da.
10 Modu zorrotza ("use strict")
JavaScript hasiera batean oso malgua izateko diseinatu zen. Lehen urteetan, detektatzeko zailak ziren akatsak sor zitzaketen ekintza batzuk egitea ahalbidetzen zuen, hala nola aldagaiak deklaratu gabe sortzea edo gomendagarriak ez ziren egiturak erabiltzea. Segurtasuna hobetzeko eta aplikazioen garapena errazteko, ECMAScript 5 (ES5) estandarrak modu zorrotza (Strict Mode) txertatu zuen 2009an.
Modu zorrotza fitxategi edo funtzio baten hasieran honako instrukzio hau idatziz aktibatzen da:
Modu zorrotza gehitu
"use strict";
Une horretatik aurrera, interpretatzaileak arau zorrotzagoen multzo bat aplikatzen du, garapenean zehar akatsak detektatzen laguntzen duena. Adibidez, aldagaiak nahi gabe sortzea eragozten du, segurutzat jotzen ez diren zenbait eragiketa saihesten ditu eta lehen oharkabean pasa zitezkeen egoeretan salbuespenak sortzen ditu. Horrek akatsak detektatzea errazten du eta kode sendoagoa eta mantentzeko errazagoa idazten laguntzen du.
Gaur egun, ECMAScript moduluak (import eta export erabiltzen dituzten fitxategiak) modu zorrotzean funtzionatzen dute automatikoki, eta, beraz, ez da beharrezkoa goiburua haietan idaztea. Hala ere, oraindik ere gomendagarria da direktiba hori ezagutzea, proiektu ugaritan erabiltzen jarraitzen baita eta moduluak hedatu aurretik garatutako aplikazioen funtzionamendua ulertzea ahalbidetzen baitu.
Liburu honetan zehar JavaScript-en ezaugarri modernoak erabiliko ditugu beti, eta lengoaiaren egungo gomendioei jarraituko diegu. Proiektu moderno askotan modu zorrotza dagoeneko automatikoki aktibatzen bada ere, haren helburua ezagutzeak JavaScript-en bilakaera eta garapenaren hasieratik jardunbide egokiak hartzearen garrantzia ulertzen laguntzen du.
Sortu JavaScript fitxategi bat ondorengo kodearekin. Zer gertatzen da?
Modu zorrotza
"use strict";
nombre = "Ana";
console.log(nombre);
11 Iruzkinak
Iruzkinak iturburu-kodean txertatutako testu-zatiak dira, JavaScript-en exekuzio-motorrak exekutatzen ez dituenak. Haien helburua programaren funtzionamendua ulertzen laguntzea, diseinu-erabakiak dokumentatzea edo garapenean zehar zenbait instrukzio aldi baterako desaktibatzea da.
Beste lengoaia batzuetan gertatzen den bezala, lerro bakarreko edo hainbat lerrotako iruzkinak egin ditzakegu.
Lerro bateko iruzkina
// Este es un comentario
console.log("Hola mundo");
let edad = 20; // edad
Lerro askotako iruzkina
/*
Este comentario puede ocupar
una o varias líneas.
*/
console.log("Hola");
Iruzkinek kodeari informazio erabilgarria eman beharko liokete; beraz, ez lirateke lerro bakoitza azaltzeko erabili behar. Ohikoena honako kasu hauetan erabiltzea da:
- Algoritmo konplexuak.
- Diseinu-erabakiak.
- Agerikoak ez diren soluzioak.
- Ezagutzen diren mugak.
- Aldatzeko zain dagoen kodea.
Iruzkinak eguneratuta mantendu behar dira kodea eguneratu ahala.
11.1 JSDoc iruzkinak
Beste programazio-lengoaia batzuetan gertatzen den bezala, proiektu profesionaletan ohikoa da dokumentaziorako formatu berezi bat erabiltzea. Javan Javadoc erabili ohi da eta, JavaScript-en, antzeko sintaxia erabiliz, JSDoc erabil daiteke.
Funtzioak, klaseak eta programaren beste elementu batzuk modu egituratuan dokumentatzea ahalbidetzen du. Haren sintaxia /** erabiliz hasten da.
JSDoc iruzkinak
/**
* Devuelve la suma de dos números.
*
* @param {number} a Primer número.
* @param {number} b Segundo número.
* @returns {number} Resultado de la suma.
*/
function sumar(a, b) {
return a + b;
}
12 Aldagaiak
Aldagaiek informazioa memorian gordetzeko aukera ematen dute, gero erabili ahal izateko. Horiei esker, programa batek balioak gogora ditzake, kalkuluak egin, informazioa aldatu edo kodearen atal desberdinen artean datuak trukatu.
Aldagai bat sortu eta erabili
let nombre = "Alice";
console.log(nombre);
Kasu honetan:
- let: aldagai bat deklaratuko dugula adierazten du.
- nombre: identifikatzailea da.
- "Alice": gordetako balioa da.
- console.log(nombre);: aldagaiaren erabilera
Aldagai baten izenari identifikatzaile deitzen zaio, eta hainbat arau bete behar ditu. Honako hauek izan ditzake:
- Letrak.
- Digituak (hasieran izan ezik).
- Beheko marra (
_). - Dolar ikurra (
$).
Logikoa denez, ezin dira hitz erreserbatuak erabili aldagaien identifikatzaile gisa. Garrantzitsua da jakitea, halaber, JavaScript case sensitive dela; beraz, nombre eta Nombre ez dira gauza bera.
JavaScript case sensitive da. Kontuz identifikatzaileak erabiltzean.
12.1 Deklarazioa eta hasieratzea
Garrantzitsua da bi kontzeptu bereiztea.
- Aldagaia deklaratzea: aldagaia sortzean datza. Oraindik ez du baliorik.
- Aldagaia hasieratzea: lehen aldiz balio bat esleitzean datza.
- Bi ekintzak aldi berean egin daitezke.
Definitu
let edad;
Balioa eman
edad = 20;
Biak
let edad = 20;
12.2 let, const eta var arteko desberdintasunak
Aldagaiak deklaratzeko hiru hitz erreserbatu erabil ditzakegu:
- let: Balioa alda daitekeen aldagaiak deklaratzeko gomendatutako modua da.
- const: Konstante bat deklaratzen du. Konstante batek balio bat jaso behar du sortzen den unean. Konstante batek objektu edo array bat gordetzen duenean, konstante mantentzen dena objektuaren erreferentzia da, ez nahitaez haren edukia. Hitzarmen bidez, konstante batek balio finko global bat adierazten duenean, maiuskulaz idatzi ohi da.
- var: ECMAScript 2015 baino lehen aldagaiak deklaratzeko erabiltzen zen, baina ez da gomendatzen kode berrian erabiltzea. Arrazoia da portaera desberdina duela aldagaien esparruari eta goratzeari (hoisting) dagokienez, eta horrek detektatzeko zailak diren akatsak eragin ditzake.
“let”-ekin
let contador = 0;
contador++;
contador++;
console.log(contador);
Konstante
const PI = 3.141592;
PI = 3; // TypeError:
const letras = ["a", "b"];
// permitido
letras.push("c");
“var”-ekin
var nombre = "Ana";
12.3 Aldagaien esparrua
Esparruak (scope) zehazten du programaren zein ataletatik atzi daitekeen aldagai batera. Lau esparru daude:
- Global scope: script moduan dagoen kode guztiaren esparru lehenetsia.
- Module scope: moduluetako kodearen esparrua (aurrerago ikusiko dugu).
- Function scope: funtzio beraren barruko esparrua.
- Block scope: let eta const aldagaientzat, giltzen artean dagoen esparrua (a bloke).
Laburpen gisa, ondorengo taula erabil dezakegu:
| let | const | var | |
|---|---|---|---|
| Esparrua (scope) | Blokea | Blokea | Funtzioa/Globala |
| Berriro deklaratzea | Bai | Ez | Bai |
| Berriro esleitzea | Bai | Ez | Bai |
| Gomendatutako erabilera | Aldatzen diren aldagaietarako | Balio finko edo erreferentzietarako | Saihestu |
Garrantzitsua da aldagaien scopea kontuan hartzea, akatsak saihesteko.
12.4 Izenak jartzeko konbentzioa
JavaScript-ek hainbat izen erabiltzeko aukera ematen du, baina badira oso onartuak dauden konbentzioak.
- camelCase: JavaScript-en erabiltzen den konbentzioa da. Lehenengo hitza minuskulaz hasten da, eta hurrengoak maiuskulaz. Izenen adibideak: nombreCompleto, numeroAlumnos, fechaNacimiento, …
- Snake_Case: Python-en, PHP-n, … erabiltzen da. Izenen adibideak: nombre_completo, numero_alumnos, …
Bestalde, aldagaien hizkuntza, iruzkinak nola idatzi… erabaki beharko genuke. Hori guztia programatzaileek erabiltzen duten hizkuntzaren, kodea argitaratuko den ala ez, eta abarren araberakoa izango da.
Garrantzitsuena konbentzio bat aukeratzea eta beti mantentzen saiatzea da.
13 Datu motak
Programa batek kudeatzen duen informazio guztia datu moduan gordetzen da. JavaScript-ek hainbat datu motarekin lan egin dezake, hala nola zenbakiekin, testuekin, balio logikoekin, elementuen zerrendekin edo objektuekin. Datu mota desberdinak ezagutzea funtsezkoa da programa zuzenak idazteko eta akatsak saihesteko.
JavaScript tipatze dinamikoko lengoaia da; horrek esan nahi du aldagai bat deklaratzean ez dela beharrezkoa haren mota adieraztea. Javan edo C-n ez bezala, programatzaileak aldagaien mota adierazi behar baitu, JavaScript-en lengoaia bera arduratzen da mota automatikoki zehazteaz, esleitutako balioaren arabera.
13.1 Mota primitiboak
Beste programazio-lengoaia batzuek bezala, JavaScript-ek balio bat adierazten duten datu-mota primitibo batzuk ditu:
- Boolean: true eta false izan daitezkeen balioak soilik.
- null: Balio nulua dela adierazten duen hitz berezia.
- undefined: Oraindik deklaratu ez diren aldagaiei esleitzen zaien balio primitiboa.
- Number: Zenbaki osoa edo koma mugikorreko zenbakia. Adibidez: 42 edo 3.14159.
- Infinity eta -Infinity balioak sor ditzake; balio horiek izan daitezkeen gehienezko eta gutxieneko balioak adierazten dituzte.
- NaN: Not a Number, datu mota bat zenbakia den jakiteko eragiketaren emaitza; kasu honetan, ez da zenbakia: Number("hola")
- BigInt: zehaztasun arbitrarioko zenbaki osoa. Adibidez: 9007199254740992n.
- String: Testu bat osatzen duten karaktereen sekuentzia. Honela idatz daiteke:
- Komatxo bakunak: 'hola'
- Komatxo bikoitzak: "hola"
- Alderantzizko komatxoak: `hola`
- Symbol: Unibokoa eta aldaezina dela bermatzen duen datu mota.
Datu-moten adibidea
let verdadero = true;
let falso = false;
let nulo = null;
let edad = 18;
let temperatura = 22.5;
let saldo = -150.75;
// Infinity
console.log(42 / 0);
// -Infinity
console.log(-42 / 0);
Datu-moten adibidea
let nombre = "Charlie";
let ciudad = 'Bilbao';
let saludo = `Hola`;
console.log("Hola "+nombre)
console.log("Hola %s",nombre)
console.log(`Hola ${nombre}`)
let edad;
// undefined
console.log(edad);
13.2 Objektuak
Aurretik deskribatu ez diren gainerako datu-motak Object motakoak dira. Horien artean funtzioak, array-ak, adierazpen erregularrak, Map edo Error motako objektuak egon daitezke.
Objektu baten adibidea honako hau izango litzateke:
Object adibidea
const alumno = {
nombre: "Alice",
edad: 20,
aprobado: true
};
console.log(alumno.nombre)
Aurrerago, Objektuak atalean sakonduko dugu.
13.3 typeof eragilea
JavaScript-ek typeof eragilea dauka, datu baten mota ezagutzeko aukera ematen duena.
typeof operadorea
let nombre = "Bob";
typeof nombre;
13.4 Mota bihurketa
Askotan beharrezkoa da datu-mota bat beste batera bihurtzea; batzuetan aldi baterako, eta beste batzuetan behin betiko. Bihurketa esplizitua azalduko dugu, geroago eragileekin azalduko diren bihurketa inplizituen kasu batzuk baitaude.
Datuen bihurketa
let edad = Number("25");
//NaN
Number("Hola")
parseInt("123")
// 123
parseInt("123px")
parseInt(123.4)
parseFloat("12.75")
Datuen bihurketa
String(25)
String(true)
Boolean(1)
Boolean("123")
Boolean(0)
Boolean("")
Boolean(null)
Boolean(undefined)
Boolean(NaN)
Egin proba bat ikusitako mota-bihurketa desberdinekin.
13.5 == eta === arteko konparaketa
JavaScript-ek lehenespenez egiten dituen bihurketa automatikoen ondorioz, konparaketa-eragileak bereziki eragiten ditu. Horren ondorioz, batzuetan nahi ez ditugun akatsak izan ditzakegu gure kodean:
Bihurketa automatikoak saihesteko, === edo strict equality eragilea dago. Eragile horrek Boolean bat itzultzen du, eta bai balioa bai datu-mota hartzen ditu kontuan.
Zein emaitza ematen dituzte ondorengo eragiketek?
- 5 === 5
- 5 === "5"
- 1 === true
- 0 === false
- Symbol(42) === Symbol(42)
- typeof Symbol(42) === typeof Symbol(42)
Ezeztapen-eragilea !== da.
Konparaketak egiterakoan === erabiltzea gomendatzen da.
14 Eragileak
Eragileek balio baten edo gehiagoren gainean eragiketak egiteko aukera ematen dute. Horiei esker, kalkulu matematikoak egin, datuak konparatu, baldintzak konbinatu, balioak esleitu edo aldagaiak aldatu daitezke. Ez ditugu guztiak aztertuko, asko baitira, baina guztiak MDNren dokumentazioan aurki daitezke, eta “familien” arabera bereizita daude (esleipenekoak, konparaketakoak, aritmetikoak…).
14.1 Eragile aritmetikoak
Eragile aritmetikoek eragiketa matematikoak egiteko aukera ematen dute.
| Eragilea | Deskribapena | Adibidea |
|---|---|---|
+ |
Batuketa | 5 + 2 |
- |
Kenketa | 5 - 2 |
* |
Biderketa | 5 * 2 |
/ |
Zatiketa | 5 / 2 |
% |
Zatiketaren hondarra | 5 % 2 |
** |
Berreketa | 5 ** 2 |
14.2 Esleipen-eragileak
Aldagai batean balio bat gordetzeko aukera ematen dute. Erabiliena = eragilea bada ere, eragiketak modu laburtuan idazteko aukera ematen diguten beste eragile batzuk ere badaude.
| Eragilea | Honen baliokidea |
|---|---|
+= |
x = x + valor |
-= |
x = x - valor |
*= |
x = x * valor |
/= |
x = x / valor |
%= |
x = x % valor |
**= |
x = x ** valor |
Idatzi aurreko esleipen bakoitzaren adibide bat.
14.3 Gehikuntza eta txikitze-eragileak
Aldagai bat unitate batean handitzeko edo txikitzeko aukera ematen dute. Aldagaiaren aurretik edo ondoren jar daitezke, eta kokatzen diren lekuaren arabera haien portaera aldatu egiten da.
Gehitu
let x = 5;
x++;
console.log(x++);
console.log(++x);
Kendu
let x = 5;
x--;
console.log(x--);
console.log(--x);
Zein da aurreko kodearen emaitza?
14.4 Konparaketa-eragileak
Bi balio konparatzeko aukera ematen dute. Emaitza beti balio boolearra da: true edo false.
| Eragilea | Esanahia |
|---|---|
| > | Handiagoa |
| < | Txikiagoa |
| >= | Handiagoa edo berdina |
| <= | Txikiagoa edo berdina |
| == | Berdina (bihurketa automatikoarekin) |
| != | Desberdina (bihurketa automatikoarekin) |
| === | Berdintasun zorrotza |
| !== | Desberdintasun zorrotza |
Aurreko atalean ikusi dugun bezala, === eta !== erabiltzea gomendatzen da.
14.5 Eragile logikoak
Hainbat baldintza konbinatzeko aukera ematen dute. Aurrerago erabiliko ditugu baldintzazko sententzien atalean.
| Eragilea | Esanahia |
|---|---|
&& |
Eta logikoa (AND) |
|| |
Edo logikoa (OR) |
| ! | Ezeztapena (NOT) |
14.6 Kateatzeko eragilea
+ eragilea testu-kateak elkartzeko ere erabil daiteke, baina gaur egun normalean nahiago izaten da template literals erabiltzea.
Testua kateatzea
const nombre = "John";
const apellido = "Doe";
console.log(nombre + " " + apellido);
// mejor así
console.log(`Hola ${nombre} ${apellido}`);
14.7 Ezkerreko balioa nulua bada esleitzeko eragilea ??
nullish coalescing assignment eragilea dago. Eskuineko datua soilik hartzen du ezkerrekoak null edo undefined balio duenean.
Nullish coalescing assignment
const a = { duration: 50 };
a.speed ??= 25;
console.log(a.speed);
// Salida esperada: 25
a.duration ??= 10;
console.log(a.duration);
// Salida esperada: 50
Eragile horrek existitzen ez diren balioekin lotutako akats asko saihesten ditu.
15 Datuen sarrera eta irteera
Programa orok erabiltzailearekin komunikatu behar du, eta normalean komunikazio horrek honako hauek hartzen ditu barne:
- Informazioa erakustea.
- Datuak eskatzea.
- Akats-mezuak erakustea.
- Ekintza bat berrestea.
JavaScript-en hainbat mekanismo daude zeregin horiek egiteko. Hasiera batean Web formatuan izan beharko lukeen arren, hasteko beste modu batzuk ikusiko ditugu, eta horrela debugging egiteko ere erabili ahal izango ditugu.
15.1 Kontsolaren bidezko irteera
Garapenean zehar ohikoena nabigatzailearen kontsola erabiltzea da. Orain arte erabiltzen ari garen funtzioa da, eta gehien erabiltzen dena. log formatuaz gain, ondoren zehazten diren beste metodo batzuk ere erabil ditzakegu:
Azken bi metodoetan, nabigatzaile batzuek kolore edo ikono desberdinak erabiliz erakusten dituzte.
15.2 Datuak eskatzea prompt() bidez
prompt() funtzioak erabiltzaileari informazioa eskatzen dion leiho bat erakusten du. Erabiltzaileak balioa idatzi eta Onartu botoia sakatu beharko du. Balioa aldagai batean gorde beharko da.
prompt() funtzioak beti testu-kate bat itzultzen du.
Gaur egun funtzio hau ez da erabiltzen, hainbat eragozpen baititu eta haren funtzionalitatea inprimakien bidez lor baitaiteke:
- Programaren exekuzioa eteten dute.
- Orriaren interakzioa blokeatzen dute.
- Itxura nabigatzailearen araberakoa da.
- Ezin dira pertsonalizatu.
Eskatu prompt() bidez izen-abizenak, eta erabili kontsola datuak template literals erabiliz erakusteko.
15.3 Mezuak alert() bidez erakustea
alert() funtzioak mezu bat duen leiho bat erakusten du. Programa geldituta geratzen da erabiltzaileak onartzeko botoia sakatu arte. Gaur egun ia ez da erabiltzen, prompt() funtzioaren arrazoi berberengatik.
alert metodoa
alert("Bienvenido");
15.4 Egiaztapena confirm() bidez eskatzea
confirm() funtzioak bi botoi dituen galdera bat erakusten du, Onartu edo Utzi aukeratzeko, eta boolean balio bat itzultzen du.
confirm metodoa
const borrar = confirm("¿Desea eliminar el registro?");
Berriro ere, ia erabiltzen ez den funtzioa da, ohikoa baita modals erabiltzea.
15.5 Informazioa orrian erakustea
Kontsolaz gain, JavaScript-ek web-orri baten edukia alda dezake. Aurrerago sakonago aztertuko dugu, baina ondorengo adibidea aurrerapen gisa erabil dezakegu.
index.html
<p id="mensaje"></p>
Código js/app.js
document.getElementById("mensaje").textContent = "Hola!";
16 Kontrol-egiturak
Orain arte aldagaiak deklaratzen, informazioa gordetzen eta haiekin eragiketak egiten ikasi dugu. Orain arte ikusi dugun guztian, instrukzioak modu sekuentzialean exekutatzen dira, bata bestearen atzetik. Programa batek erabakiak hartzeko, zereginak errepikatzeko edo sartutako informazioaren arabera instrukzio batzuk edo beste batzuk exekutatzeko gai izan behar du.
Kontrol-egiturek programa baten exekuzioaren fluxu normala aldatzeko aukera ematen dute, eta haiei esker aplikazio konplexu eta dinamikoak sor ditzakegu. Aurreko ikasturtean ikusi zenuten bezala, kontrol-egiturak honela bereizten dira:
- Egitura sekuentzialak: bata bestearen atzetik exekutatzen dira.
- Baldintzazko egiturak: baldintza baten arabera instrukzioak exekutatzen dituzte.
- Egitura errepikakorrak: bloke bat hainbat aldiz exekutatzeko aukera ematen dute.
16.1 Baldintzazko egiturak
Beste programazio-lengoaia batzuetan bezala, if baldintzazko egitura da sinpleena, eta eduki bat exekutatuko du baldintza bat betetzen bada. Baldintza hori betetzen ez bada eta else blokea badago, bigarren bloke hori exekutatuko da.
Baldintza sinple
const edad = 20;
if (edad >= 18) {
console.log("Mayor");
}
Baldintza else-rekin
const edad = 20;
if (edad >= 18) {
console.log("Mayor");
} else {
console.log("Menor");
}
Eskatu prompt() bidez adina, eta erabili baldintzazko egitura adin hori nagusia edo adingabea den jakiteko.
Baldintzan aurrez ikusitako konparaketa-eragileak erabil daitezke, eta baldintza bat baino gehiago kateatu nahi baditugu, eragile logikoak.
Operadore logikoa
const edad = 20;
if (edad >= 18 && edad <=65) {
console.log("Mayor");
} else {
console.log("Menor o jubilado");
}
Baldintza “else if”-rekin
let edad = 20;
if (edad >= 65) {
console.log("Jubilado");
} else if (edad >= 18){
console.log("Mayor");
} else {
console.log("Menor");
}
Ikus daitekeen bezala, else if ere erabil daiteke aurreko baldintzan betetzen ez den baldintza berri bat egiaztatu nahi badugu.
Eskatu prompt() bidez adina, eta erabili baldintzazko egitura adina adingabea, nagusia edo erretiroduna den jakiteko.
16.1.1 Eragile ternarioa
if..else egitura sinple bat idatzi nahi badugu, lerro bakarrean eragile ternarioa erabil dezakegu honela:
Operador ternario
const edad = 20;
const mensaje = edad >= 18 ? "Mayor" : "Menor";
16.1.2 switch estruktura
Hainbat baldintza egiaztatu nahi baditugu, if else egiturak habiaratu behar ez izateko, switch erabil dezakegu:
Usando switch
switch (action) {
case "draw":
console.log("draw");
break;
case "eat":
console.log("eat");
break;
default:
console.log("default");
}
Garrantzitsua da bloke bakoitzaren amaieran break sententzia gehitzea; izan ere, hala egin ezean, gainerako mailak “ur-jauzian” exekutatzen jarraituko du. default blokea aurreko blokeetako batekin ere bat ez datorrenean exekutatuko da.
Erabili switch baldintzazko egitura, break erabiliz eta erabili gabe.
17 Bukleak
Sententzia errepikakorrak eta blokeen exekuzio errepikatuak egiteko, egitura errepikakorrak erabiltzen dira, bukleak/begiztak ere deituak.
Bukle batek instrukzio-bloke bat hainbat aldiz exekutatzeko aukera ematen du, betiere baldintza jakin bat betetzen bada. Beste programazio-lengoaia batzuetan gertatzen den bezala, JavaScript-en hainbat bukle mota daude:
17.1 while bukle
while buklea bloke bat exekutatzen du baldintza egia den bitartean. Baldintza iterazio bakoitzaren aurretik ebaluatzen da, eta, beraz, baldintza faltsua bada, bukle ez da exekutatuko.
Bukle while
let contador = 1;
while (contador <= 5) {
console.log(contador);
contador++;
}
Bukle infinitua
let contador = 1;
while (contador <= 5) {
console.log(contador);
}
Garrantzitsua da baldintza kontuan hartzea bukle infinituak saihesteko.
17.2 do…while bukle
Kasu honetan, baldintza blokea exekutatu ondoren ebaluatzen da.
Bulle do…while
let contador = 1;
do {
console.log(contador);
contador++;
} while (contador <= 5);
17.3 for bukle
Aldez aurretik errepikapen kopurua ezagutzen dugunean gehien erabiltzen den bukle da.
Bukle for
for (let i = 1; i <= 5; i++) {
console.log(i);
}
Kasu honetan, sententziaren barruan hiru zati bereizten dira:
- Hasieratzea: let i = 0
- Baldintza: i < 10
- Eguneratzea: i++
Sortu ikusitako bukle bakoitzaren adibide bat.
17.4 for…of bukle
JavaScript modernoak for…of bukle dauka, objektu iterableak (Array, Map, Set…) zeharkatzeko diseinatua.
Array-ak zeharkatzeko gomendatutako modua da.
Bukle for…of
const colores = ["Rojo", "Verde", "Azul"];
for (const color of colores) {
console.log(color);
}
17.5 for…in bukle
for…in buklearekin objektu baten propietateak zeharka daitezke.
Bukle for…in
const alumno = {
nombre: "Bob",
edad: 20
};
for (const propiedad in alumno) {
console.log(propiedad);
}
Array-etan ere erabil daiteke, baina ez da gomendagarria. Array-ak zeharkatzeko beti for…of erabiliko dugu.
17.6 Bukleen laburpena
Ondorengo taulan bukle moten laburpena eta bakoitza zertarako erabili beharko genukeen ikus daiteke.
| Egoera | Gomendatutako bukle |
|---|---|
| Errepikapen kopuru ezaguna | for |
| Baldintza bat betetzen den bitartean errepikatzea | while |
| Gutxienez behin exekutatzea | do...while |
| Array-ak zeharkatzea | for...of |
| Objektuen propietateak zeharkatzea | for...in |
17.7 break eta continue sententziak
Batzuetan beharrezkoa da bukle baten ohiko portaera aldatzea, eta horretarako honako instrukzio hauek ditugu:
- break: buklea berehala amaitzen du.
- continue: uneko iterazioa saltatzen du eta hurrengoarekin jarraitzen du.
break
const numeros = [4, 8, 15, 23];
for (const numero of numeros) {
if (numero === 15) {
console.log("Encontrado");
break;
}
}
continue
for (let i = 1; i <= 5; i++) {
if (i === 3) {
continue;
}
console.log(i);
}
Sortu ikusitako bukle bakoitzaren adibide bat.
18 Oinarrizko erroreen kudeaketa
JavaScript-ek akatsak detektatzeko eta kudeatzeko aukera ematen du, aplikazioa ustekabean amaitu ez dadin.
18.1 try…catch egitura
Programazio-lengoaia askotan dagoen salbuespenen kudeaketarako egitura try…catch da, eta JavaScript ez da salbuespena.
Akats bat sortzeko joera duen sententzia bat exekutatzen badugu, programa gelditu egin daiteke. Sententzia hori try…catch baten barruan exekutatzen badugu, akatsaren kudeaketa kontrola dezakegu.
Erroreen kudeaketaren adibidea
try {
console.log(variableInexistente);
}
catch (error) {
console.log("Error: "+error);
}
18.1.1 error objektua
catch blokeak erroreari buruzko informazioa duen objektu bat jasotzen du, bi atributu dituena:
- name: errorearen izena.
- message: errore-mezua.
18.1.2 finally blokea
try…catch blokearekin batera, finally izeneko aukerako bloke bat gehi dezakegu, eta beti exekutatuko da, errorea egon zein ez.
Erroreen kudeaketa
try {
console.log("Inicio");
}
catch (error) {
console.log("Error: "+error);
}
finally {
console.log("Fin");
}
18.2 Erroreak throw bidez sortzea
Erroreak nahita sortzea ere posible da throw sententziaren bidez.
Erroreak sortzeko adibidea
const edad = -5;
if (edad < 0) {
throw new Error("La edad no puede ser negativa.");
}
19 Funtzioak
Orain arte, instrukzio-sekuentzia batez osatutako programak idatzi ditugu. Programak handitzen diren heinean, ohikoa da beti zeregin bera egiten duten kode-blokeak aurkitzea. Kode hori hainbat aldiz kopiatu eta itsasteak programa mantentzea zailagoa egiten du eta akatsak egiteko probabilitatea handitzen du.
Funtzioek instrukzio multzo bat izen baten pean taldekatzeko aukera ematen dute, beharrezkoa den bakoitzean exekutatu ahal izateko. Funtzioak edozein programazio-lengoaiaren elementu garrantzitsuenetako bat dira.
19.1 Funtzioen deklarazioa eta erabilera
Funtzio bat sortzeko modu klasikoan function hitz erreserbatua erabiltzen da. Funtzioari deitzeko, hitz erreserbatu hori erabiliko dugu () parentesiekin batera.
Funtzioa sortu
function saludar() {
console.log("Hola.");
}
Funtzioari deitu
saludar();
saludar();
function bidez deklaratutako funtzioak kodean agertu aurretik ere erabil daitezke.
19.2 Parametroak
Askotan, funtzio batek datu desberdinekin lan egin behar du exekutatzen den bakoitzean, eta horretarako parametroak erabiltzen dira. Parametro bat funtzioari deitzean balio bat jasotzen duen aldagaia da. Funtzio batek hainbat parametro jaso ditzake.
Funtzioa sortu
function saludar(nombre) {
console.log(`Hola ${nombre}`);
}
Funtzioari deitu
saludar("Ann");
saludar("Bob");
Nahiz eta ohikoa den “parametroa” eta “argumentua” sinonimotzat erabiltzea, bada alde txiki bat:
- Parametroa: funtzioan definitutako aldagaia.
- Argumentua: funtzioari deitzean pasatzen zaion balioa.
19.2.1 Balio lehenetsia
ECMAScript 2015etik aurrera, parametroei balio lehenetsia esleitzea posible da. Horrela, funtzioari deitu diezaiokegu parametroa gehituz edo gehitu gabe.
Funtzioa sortu
function saludar(nombre="Usuario") {
console.log(`Hola ${nombre}`);
}
Funtzioari deitu
saludar();
saludar("Alice");
Sortu balio lehenetsia duen funtzio baten adibidea.
19.2.2 Argumentuak pasatzea
Beste programazio-lengoaia batzuetan, funtzio bat deklaratzean, parametro kopuru berarekin deitu behar dugu. Halaber, normalean funtzio-identifikatzaile bera parametro desberdinekin erabiltzeko aukera ematen dute; horri funtzioen gainkarga esaten zaio. JavaScript-en ez da horrelakorik gertatzen, ez baitu behartzen parametroen kopuru bera duten argumentuak zehazki ematera. Hau abantailatzat har daiteke, baina kontuz ibili behar da.
Funtzioa sortu
function sumar(a, b) {
console.log(a+b);
}
Funtzioari deitu
sumar(4);
Bigarren parametroak, argumenturik pasatu ez zaionez, undefined balioa izango du. Horregatik, komeni da beharrezkoa denean parametro lehenetsiak erabiltzea edo funtzioa sortzean hori kontuan hartzea.
Sortu parametroak dituen funtzio baten adibidea.
19.3 Itzulera-balioa
Funtzio askok ez dute zeregin bat bakarrik egiten, emaitza bat ere sortzen dute. Horretarako, return hitz erreserbatua erabiltzen da emaitza itzultzeko.
Funtzioa sortu
function sumar(a, b) {
return a + b;
}
Funtzioari deitu
let resultado = sumar(4,6);
console.log(resultado);
Funtzio batek return ez badu, lehenespenez itzultzen duen balioa undefined da.
return exekutatzen denean, funtzioa amaitu egiten da. return ez badago, lehenespenez undefined itzultzen du.
Sortu itzulera-balioa duen funtzio baten adibidea.
19.4 Funtzio anonimoak eta gezi-funtzioak (arrow functions)
JavaScript modernoak funtzio anonimoak sortzeko sintaxi bat du, izenik/identifikatzailerik ez duten funtzioak definitzeko modu trinkoagoa eskaintzen duena. Funtzio anonimoak sortzeko beste modu bat “gezi-funtzioak” (arrow functions) deritzenak dira.
Funtzio anonimoak erabiltzen dira haien kodea berrerabiltzea beharrezkoa ez denean, balioak zuzenean aldagai bati esleitzeko, beste funtzio bati argumentu gisa pasatzeko edo funtzio batetik itzultzeko.
Jarraian, funtzio anonimoen hainbat adibide eta erabil daitekeen sintaxia ikus daitezke.
Funtzio anonimoa
const m = function(x, y){
return x * y;
};
Gezi-funtzioa
const m = (x, y) => {
return x * y;
}
Gezi-funtzioa
const m = (x, y) => x * y;
Gezi-funtzioa
const m = () => "Hola!";
Sortu funtzio anonimoen eta gezi-funtzioen hainbat adibide.
Objetuak
20 Objektuak
Orain arte datu bakarra gordetzeko gai diren aldagaiekin lan egin dugu, baina, dagoeneko dakigunez, benetako aplikazio batean normalean entitate eta datu konplexuagoak erabiltzen ditugu. Horren ondorioz, aldagai independenteak soilik erabiltzea ez da eraginkorra eta ez da oso errealista.
JavaScript-en objektuak erabil ditzakegu, erlazionatutako informazioa taldekatzea ahalbidetzen duen egitura bat baitira. Objektu baten barruko datu bakoitza propietate bat da, eta komatxoekin edo komatxorik gabe deklara daiteke (normalean, komatxorik gabe). JavaScript-eko objektuetatik JSON formatua (JavaScript Object Notation) eratorri da, gaur egun Interneten oso erabilia, XML-aren alternatiba gisa.
Sortu objektu berria
const alumno = {
nombre: "Alice",
edad: 20,
direccion: {
ciudad: "Bilbao",
calle: "una",
}
};
Sortu objektu berria
const alumno = {
"nombre": "Bob",
"edad": 20,
"direccion": {
"ciudad": "BI",
"calle": "una",
}
};
Sortu objektu berria
const nombre = "Bob";
const edad = 30;
const alumno = {
nombre,
edad,
//...
};
Aurreko adibidean alumno objektua dugu, hiru propietat eta bakoitzari dagokion balioarekin. Objektuak alda daitezke, nahiz eta const erabiliz deklaratu diren, edukia aldatzen ari garelako, eta ez erreferentzia (hau da const-ek babesten duena).
20.1 Propietateak
Aipatu dugun bezala, objektu batek propietateen bilduma bat dauka, eta propietate horiekin hainbat eragiketa egiteko aukera dugu. Jarraian, horiek zehaztuko ditugu:
20.1.1 Propietateak atzitzea eta aldatzea
Objektu bat sortu ondoren, haren propietateen balioa kontsulta dezakegu, aldatu, propietate berriak gehitu edo ezabatu. JavaScript-ek objektu baten barruan gordetako informazioa atzitzeko hainbat modu eskaintzen ditu.
Propietateetara sartzeko bi modu erabil ditzakegu:
Propietateen baloreak lortu
console.log(alumno.nombre);
console.log(alumno.edad);
console.log(alumno.direccion.calle);
Propietateen baloreak lortu
console.log(alumno["nombre"]);
console.log(alumno["direccion"]["calle"]);
//evitad mezclar
console.log(alumno["direccion"].calle);
Kortxeteen erabilera ohikoagoa izaten da propietatearen izena aldagai batean dugunean.
Propietateen baloreak lortu
let propiedad = "direccion";
console.log(alumno[propiedad])
Propietateak aldatu
alumno.nombre = "Bob";
alumno.curso = "2º DAW";
Propietatea aldatzeko, goiko kodean ikus daitekeen modu bera erabiliko genuke. Propietate berriak gehitu nahi baditugu, gauza bera egingo dugu.
20.1.2 Propietateak ezabatzea
Propietate bat ezabatu nahi badugu, delete eragilea erabiliko dugu. Lehenespenez, beti true itzultzen du, salbuespenak badaude ere.
Propietateak kendu
delete alumno.curso;
20.1.3 Existitzen ez den propietate batera sartzea
Baliteke kasuren batean definitu gabeko propietate batera eta, beraz, existitzen ez den propietate batera sartzen saiatzea. Emaitza undefined izango da, eta, beraz, ez du errorerik sortuko.
20.1.4 Existitzen ez den objektu batera ?. bidez sartzea
Objektu bat existitu ez badaiteke, bertara edo haren propietate batera sartzen saiatzen bagara, errore bat jasoko dugu. Errore hori saihesteko, ?. eragilea erabil dezakegu (optional chaining deitzen zaio).
Existitzen ez den objektu batera sartu
const profesor = null;
console.log(profesor?.nombre); // undefined
console.log(profesor.nombre); // error
20.1.5 Egiaztatu propietate bat existitzen den
Modu erraz bat in eragilea erabiltzea da. Eragile hori erabiltzean, boolear motako balio bat lortuko dugu, eta, beraz, propietatea existitzen bada true izango dugu.
Egiaztatu propietate bat existitzen den
if ("edad" in alumno) {
console.log("tiene edad")
} else {
console.log("no tiene edad")
}
20.1.6 Propietateen zeharkatzea
Askotan beharrezkoa izaten da objektu baten propietate guztiak prozesatzea. JavaScript-ek hainbat mekanismo eskaintzen ditu propietate horiek zeharkatzeko.
20.1.6.1 for…in erabiliz
Aurretik ikusi dugu begizta erabil dezakegula. Modurik errazena for...in begizta erabiltzea da. Kasu honetan, propietateen izena soilik lortuko dugu.
for…in
const alumno = {
nombre: "Alice",
edad: 20,
ciudad: "Bilbao"
};
for (const propiedad in alumno) {
console.log(propiedad);
}
Sortu objektu bat, gehitu propietate bat, ezabatu eta zeharkatu propietate guztiak.
20.1.6.2 Propietate guztiak Object.keys() bidez lortzea
Object.keys() funtzioak objektuaren propietate guztiak dituen array bat itzultzen du.
Object.keys()
const propiedades = Object.keys(alumno);
console.log(propiedades);
// recorrer propiedades
for (const propiedad of Object.keys(alumno)) {
console.log(propiedad);
}
20.1.6.3 Propietateen balioak soilik Object.values() bidez lortzea
Balioak soilik nahi baditugu, Object.values() funtzioa erabil dezakegu.
Baloreak lortu
console.log(Object.values(alumno));
20.1.6.4 Propietatea eta balioa Object.entries() bidez lortzea
[[gakoa,balioa],…] formatuan osatutako array bat itzultzen du.
Propietatea eta balioa lortu
// recorrer propiedad/valor
for (const [propiedad, valor] of Object.entries(alumno)) {
console.log(propiedad, valor);
}
Erabili Object.entries() objektu bat zeharkatzeko.
20.1.6.5 Zein metodo erabili?
Laburpen gisa, ondorengo taula erabilgarria da.
| Metodoa | Itzultzen du |
|---|---|
| for…in | Objektuaren propietateak. |
| Object.keys() | Propietateak dituen array bat. |
| Object.values() | Balioak dituen array bat. |
| Object.entries() | Propietate-balio bikoteak dituen array bat. |
JavaScript modernoan oso ohikoa da Object.entries() for…of-ekin batera erabiltzea, sintaxi argia eta irakurtzeko erraza eskaintzen baitu, baina behar dugunaren araberakoa izango da.
Erabili une bakoitzean objektuak zeharkatzeko beharretara hobekien egokitzen den metodoa.
20.2 Metodoak
Objektuek funtzioak ere izan ditzakete, eta funtzio horiei metodo deitzen zaie. Metodoak bi modutan deklara daitezke, jarraian ikus dezakegun bezala:
Metodoa
const alumno = {
nombre: "Carol",
saludar: function () {
console.log("Hola.");
}
};
alumno.saludar();
Metodoa
const alumno = {
nombre: "David",
saludar (saludo) {
console.log(`Hola ${saludo}`);
}
};
alumno.saludar("tu");
this balioa
Metodo baten barruan, objektura bera sar gaitezke this hitz erreserbatua erabiliz.
“this” erabiltzen
const alumno = {
nombre: "Eve",
saludar() {
console.log(`Hola ${this.nombre}`);
}
};
alumno.saludar();
ez erabili gezi-funtzioak “this”-ekin
const alumno = {
nombre: "Frank",
saludar: => () {
console.log(`Hola ${this.nombre}`);
//undefined
}
};
alumno.saludar();
Teknikoki posible bada ere gezi-funtzioak metodo gisa erabiltzea, normalean ez da gomendagarria. Gezi-funtzioak erabiltzean ez dute beren this propioa sortzen, eta horrek arazoak sor ditzake emaitzekin.
Hobe da arrow functions metodo gisa erabiltzea saihestea.
Sortu metodo bat objektu baten barruan eta erabili. Sortu beste metodoa gezi-funtzioarekin eta this erabiltzen. Zer gertatzen da?
20.3 Objektuen kopia
Askotan objektu baten kopia bat sortu behar dugu, kopia aldatzeko jatorrizkoa aldatu gabe. Hala ere, JavaScript-en objektu bat kopiatzeak ez du beti espero dugun emaitza ematen. Portaera hori ulertzeko, gogoratu behar da objektuak gordetzen dituzten aldagaiek objektuaren erreferentzia gordetzen dutela, eta ez objektua bera.
Imajina dezagun objektu bat sortu eta objektu hori beste aldagai bati esleitzen diogun ondorengo adibidea:
Objektuen kopia
const alumno1 = {
nombre: "Grace",
edad: 20
};
const alumno2 = alumno1;
Gehitu edo aldatu propietate bat alumno2-n. Zer gertatzen da alumno1-ekin?
Bi aldagaiek objektu berari egiten diote erreferentzia:
Horren ondorioz, alumno2 aldatzen badugu ere, aldaketa alumno1-en ere islatuko da. Are gehiago, konparaketa === erabiliz egiten badugu, true itzuliko digu, objektu bera direlako.
Objektuen konparaketa
const alumno1 = {
nombre: "Heidi",
edad: 20
};
const alumno2 = alumno1;
console.log(alumno1 === alumno2);
const alumno3 = {
nombre: "Heidi",
edad: 20
};
console.log(alumno1 === alumno3);
Egin aurreko ariketa eta barneratu gertatzen dena.
20.3.1 Azaleko kopia
Objektuaren benetako kopia bat egiteko, Spread eragilea .. erabili behar dugu, nahiz eta Object.assign() ere erabil daitekeen.
Azaleko kopia
const alumno1 = {
nombre: "Ivan",
edad: 20,
direccion: {
ciudad: "Bilbao"
}
};
const alumno2 = {...alumno1};
console.log(alumno1 === alumno2);
Azaleko kopia
const alumno1 = {
nombre: "Alice",
edad: 20,
direccion: {
ciudad: "Bilbao"
}
};
const alumno2 = Object.assign({}, alumno1);
console.log(alumno1 === alumno2);
Aldatu adina eta hiria alumno1-en. Zer gertatzen da alumno2-n?
Kontuz, azaleko kopiak baino ez dira. Habiaratutako objektuek objektu bera izaten jarraitzen dute.
20.3.2 Kopia sakona
Objektu bat erabat kopiatu behar dugunean, habiaratutako objektu guztiak barne, kopia sakonaz (deep copy) hitz egiten dugu. Kasu horietan structuredClone() erabili behar dugu.
Kopia sakona
const alumno1 = {
nombre: "Bob",
edad: 20,
direccion: {
ciudad: "Bilbao"
}
};
const alumno2 = structuredClone(alumno1);
Aldatu adina eta hiria alumno1-en. Zer gertatzen da alumno2-n?
20.4 Objektuak konbinatzea
spread eragilea objektuak konbinatzeko ere erabil daiteke.
Objektuak konbinatu
const persona = {
nombre: "Carol"
};
const datos = {
...persona,
edad: 20,
ciudad: "Bilbao"
};
console.log(datos);
20.5 Propietateak gainidaztea
Propietate bat behin baino gehiagotan agertzen bada, azkenak izango du lehentasuna.
Propietateak gainidatzi
const alumno = {
nombre: "Dan",
edad: 20
};
const copia = {
...alumno,
edad: 21
};
21 Array-ak
Orain arte ikusi dugu objektuek erlazionatutako informazioa taldekatzea ahalbidetzen dutela; hala ere, askotan hainbat elementu gorde behar izaten ditugu. Horretarako, beste lengoaia batzuetan bezala, JavaScript-ek array-ak eskaintzen ditu.
Beste lengoaia batzuetan ez bezala, JavaScript-ek datu-mota desberdinetako elementuak dituzten array-ak sortzeko aukera ematen du. Adibiderik argiena objektuen array bat da, API batetik JSON formatuan lortzen ditugun datuak dira.
Acceder simple
const datos = [10, 20, "treinta"];
const llenar = [];
Array objektuekin
const alumnos = [
{
nombre: "Ann",
edad: 20
},
{
nombre: "Bob",
edad: 21
}
];
“Array tradizionalaz” gain, badira beste bilduma indexatu batzuk ere.
21.1 Elementuak atzitzea eta aldatzea
Array baten elementuak atzitzeko eta aldatzeko, haien indizearen bidez egin behar dugu. JavaScript-en indizeak 0-tik hasten dira.
Indize bateko balorea
console.log(datos[0]);
Indize bat aldatu
datos[2] = 30;
21.2 Array-aren luzera
Array-ak zenbat elementu dituen jakiteko, length propietatea dugu. Beraz, azken elementura sartu nahi badugu, 1 kendu beharko diogu.
Array-ren luzera
console.log(datos.length);
Azkenengo elementua
datos[datos.length-1];
21.3 Array bat zeharkatu
Modu klasikoan for begizta erabiltzen da, nahiz eta gaur egun for…of erabiltzen den.
Array zeharkatu
for (let i=0; i<datos.length; i++) {
console.log(datos[i]);
}
Array zeharkatu
for (const dato of datos) {
console.log(dato);
}
Sortu array bat, aldatu elementuren bat, egiaztatu haren luzera eta zeharkatu.
21.4 Array-en metodoak
JavaScript-ek metodo ugari eskaintzen ditu array-ekin lan egiteko. Horietako askok array-aren edukia aldatzen dute, eta beste batzuek array berri bat itzultzen dute. Jarraian, erabilienak ikusiko ditugu, baina interesgarria da array-en dokumentazioa kontsultatzea metodo guztiak ikusteko.
Array-en metodoak
const numeros = [10, 20, 30, 40, 50];
// añadir elemento al final
numeros.push(60);
// eliminar último elemento
numeros.pop();
// añadir al inicio
numeros.unshift(5);
// eliminar el primero
numeros.shift();
// obtener una parte del array
const nums = numeros.slice(1, 3);
Array-en metodoak
const colores = ["Rojo","Verde","Azul"];
// buscar un elemento
console.log(colores.includes("Verde"));
// obtener la posición
console.log(colores.indexOf("Azul"));
// concatenar arrays
const nuevo = numeros.concat(colores);
const letras = ["C", "A", "B"];
// ordenar
letras.sort();
// invertir
letras.reverse();
// convertir en cadena
console.log(colores.join(", "));
Ondorengo taulan ikusitako metodoen laburpena dago:
| Metodoa | Deskribapena |
|---|---|
| push() | Amaieran gehitzen du |
| pop() | Azkena ezabatzen du |
| unshift() | Hasieran gehitzen du |
| shift() | Lehenengoa ezabatzen du |
| includes() | Existitzen den egiaztatzen du |
| indexOf() | Posizioa itzultzen du |
| concat() | Array-ak elkartzen ditu |
| slice() | Zati baten kopia lortzen du |
| splice() | Elementuak txertatu edo ezabatzen ditu |
| sort() | Ordenatzen du |
| reverse() | Ordena alderantzikatzen du |
| join() | Testu bihurtzen du |
21.5 Array-en kopia
Objektuekin gertatzen zen bezala, array bat sortu eta beste aldagai bati esleitzen badiogu, ez dugu kopiarik egiten, datuaren erreferentzia bat baizik. Garrantzitsua da hori kontuan izatea; beraz, gogoratu objektuen kopia sakonean ikusitakoa array-ekin gauza bera egiteko.
Erabili aurreko metodoak eta kopiatu array-ak objektuekin egin dugun bezala.
Objektuetara bideratutako programazioa
22 Objektuetara bideratutako programazioa
Orain arte objektu literalak erabiltzen aritu gara, eta objektu mota hori aplikazio askotarako nahikoa bada ere, gerta daiteke egin behar dugun garapena hasieratik egitura bera duten objektu gisa planteatzea.
Adibidez, institutu bat kudeatzeko aplikazio batek ehunka ikasle kudea ditzake, eta guztiek ezaugarri berak izango dituzte, egitura bera izango dute. Objektuetara Bideratutako Programazioak (POO) eredu komun bat definitzeko aukera ematen du, behar adina objektu sortzeko.
JavaScript-ek, ECMAScript 2015etik aurrera, klaseetan oinarritutako sintaxia du, beste lengoaia moderno batzuek erabiltzen dutenaren oso antzekoa. Barnean JavaScript-ek prototipoak erabiltzen jarraitzen badu ere, klaseen bidezko sintaxiak ikaskuntza errazten du, eta gaur egun programatzeko ohiko modua da.
22.1 POOko kontzeptuen laburpena
Nahiz eta dagoeneko objektuetara bideratutako programazioa egin dugun, jarraian kontzeptu garrantzitsuenak laburbilduko ditugu:
- Klasea: objektuak nolakoak izango diren deskribatzen du.
- Objektua: klase horretatik abiatuta sortutako instantzia zehatza da.
- Propietateak/Atributuak: objektuaren egoera adierazten dute (izena, adina, …).
- Metodoak: objektuak egin ditzakeen portaera edo funtzioak adierazten dituzte.
Tradizionalki, Objektuetara Bideratutako Programazioa oinarrizko lau kontzeptutan oinarritzen da. Kontzeptu horiek dagoeneko ezagunak egin beharko litzaizkiguke, edo, gutxienez, erabiltzen jakin beharko genuke:
- Abstrakzioa: sistema bat haren funtsezko ezaugarrietan arreta jarriz adieraztean datza.
- Kapsulatzea: datuak eta datu horiekin lan egiten duten metodoak taldekatzea da.
- Herentzia: herentziari esker, aurrez existitzen den klase batetik abiatuta klase berriak sor daitezke.
- Polimorfismoa: mota desberdinetako objektuei sintaktikoki berdinak diren mezuak bidaltzeko aukera ematen duen propietateari dagokio.
23 Klase bat sortzea
Klase bat sortzeko class hitz erreserbatua erabiltzen da. Haren sintaxi orokorra jarraian ikusiko dugu, eta klasearen izena, konbentzioz, letra larriz hasi ohi da.
Beste programazio-lengoaia batzuetan ez bezala, ez da beharrezkoa eremu publikoak adieraztea, constructor bidez hasieratzen baitira. constructor metodo berezi bat da, objektu berri bat sortzen denean automatikoki exekutatzen dena. Klase bakoitzak constructor bakarra izan dezake.
Klase bakoitzak constructor bakarra izan dezake.
Klase berria
class Alumno {
constructor(nombre, edad) {
this.nombre = nombre;
this.edad = edad;
}
saludar() {
console.log(`Hola ${this.nombre}`);
}
}
Objektua sortu
const alumno1 = new Alumno("Alice",20);
const alumno2 = new Alumno("Bob",25);
alumno1.saludar();
alumno2.saludar();
Ikus daitekeenez, saludar metodo bat ere sortu da, eta klasearen objektu bat sortu ondoren deitu daiteke.
23.1 Kapsulatzea
Objektuetara Bideratutako Programazioaren oinarrizko printzipioetako bat kapsulatzea da. Objektu baten barne-egoera babestean eta bertara sartzeko modua kontrolatzean datza.
Programaren edozein atalek datuak libreki aldatzea ahalbidetu beharrean, objektuak berak erabakitzen du nola erabili behar diren.
Klase berria
class Cuenta {
constructor(saldo) {
this.saldo = saldo;
}
setSaldo(saldo){
this.saldo = saldo;
}
}
Objektua sortu
const cuenta = new Cuenta(1000);
// nada impide hacer
cuenta.saldo = -5000;
// debería ser
cuenta.setSaldo(1500);
Programazioaren ikuspegitik, eremu batera sartzea eta hura aldatzea posible da, baina horrek objektuaren portaeran eragina izan dezake. Horregatik, arazoak saihesteko, kapsulatzea erabili eta propietateak aldatzen dituzten metodoak sortu beharko genituzke.
Sortu gutxienez bi atributu eta metodo bat dituen klase bat.
23.2 Eremu eta metodo pribatuak
Bitxia badirudi ere, JavaScript-ek elementu eta metodo pribatuak 2021eko uztailean txertatu zituen. Propietate eta metodo pribatuak deklaratzeko # ikurra erabiltzen da.
Propietate eta metodo pribatu batera klase beretik soilik sar daiteke, objektuetara bideratutako programazioa duten beste lengoaia batzuetan gertatzen den bezala.
Klase berria
class Cuenta {
#saldo;
constructor(saldo) {
this.#saldo = saldo;
}
#privado() {
console.log("Priv");
}
getSaldo() {
this.#privado();
return this.#saldo;
}
}
Objektua sortu
const cuenta = new Cuenta(1000);
// obtener dato
console.log(cuenta.getSaldo());
//esto dará error
console.log(cuenta.#privado());
//esto dará error
console.log(cuenta.#saldo);
Ikus daitekeenez, propietate pribatura sartzeko, horretarako sortutako metodo bat erabili behar dugu, getSaldo(), publikoa dena. Propietatea aldatu nahi badugu ere, metodo baten bidez egin behar da.
Garrantzitsua da zehaztea Chrome nabigatzaileetan, garatzaile-kontsolatik, metodo pribatura sartzea posible dela, eta, beraz, ez duela errorerik emango.
Chrome nabigatzaileetan, garatzaile-kontsolatik, metodo pribatura sartzea posible da.
Sortu atributu eta metodo pribatu bat dituen klase bat.
23.3 Getters eta setters
Aurretik propietate batera nola sartu ikusi badugu ere, beste lengoaia batzuetako estilo klasikoa erabili dugu, Java-koa esaterako. Aldiz, JavaScript-ek getter eta setter izeneko sintaxi berezi bat eskaintzen du.
Getter batek propietate bat atributu bat balitz bezala kontsultatzeko aukera ematen du; setter-ak, berriz, propietate bat aldatzeko aukera ematen du.
Setter eta getter
class Cuenta {
#saldo;
constructor(saldo) {
this.#saldo = saldo;
}
get saldo() {
return this.#saldo;
}
set saldo(valor) {
if (valor >= 0) {
this.#saldo = valor;
}
}
}
Nola erabiltzen da
console.log(cuenta.saldo);
cuenta.saldo = 500;
console.log(cuenta.saldo);
Hartu aurreko ariketetako klase bat eta aldatu, getters eta setters erabiltzeko.
24 Herentzia
Herentzia lehendik dagoen beste klase batetik abiatuta klase berri bat sortzean datza. Klase berriak jatorrizko klasearen propietateak eta metodoak heredatzen ditu. JavaScript-en extends hitz erreserbatua erabiltzen da herentzia egiteko.
Klase alabak bere constructor propioa definitzen duenean, klase gurasoaren constructor-ari deitu behar dio super() bidez. Jakina, klase berri horrek funtzio berriak betetzen dituzten atributu eta metodo berriak ere izan ditzake.
Klase
class Persona {
constructor(nombre, edad) {
this.nombre = nombre;
this.edad = edad;
}
saludar() {
console.log(`Hola,
soy ${this.nombre}`);
}
}
Klase eta herentzia
class Alumno extends Persona {
constructor(nombre, edad, curso) {
super(nombre, edad);
this.curso = curso;
}
}
const alumno = new Alumno(
"Ana",20,"2º DAW"
);
alumno.saludar();
Sortu klase bat, lehenengo klasetik heredatzen duen beste klase bat eta atributu eta metodo berri bat dituena.
25 Polimorfismoa
Polimorfismo hitzak literalki forma asko esan nahi du. Objektuetara Bideratutako Programazioan, objektu desberdinek metodo berari modu desberdinean erantzun diezaioketela adierazten du.
Aurreko adibideko “Persona” klasea kontuan hartuta, jarraian bi klase berri sortu dira, bertatik heredatzen dutenak eta saludar() metodoa gainidazten dutenak.
Polimorfismoa
class Alumno extends Persona {
saludar() {
super.saludar();
console.log("Soy alumno.");
}
}
Polimorfismoa
class Profesor extends Persona {
saludar() {
super.saludar();
console.log("Soy profesor.");
}
}
Kontuan izan klase gurasoaren metodoari deitzeko super.saludar() erabili dela, eta horrek gurasoaren behar dugun metodoari egiten diola erreferentzia.
Aurreko adibidetik abiatuta, sortu klase bakoitzaren instantzia bat eta deitu haren saludar() metodoari.
26 Propietate eta metodo estatikoak
Metodo estatiko bat static hitz erreserbatuaren bidez deklaratzen da, eta ez da objekturik sortu behar hura erabiltzeko. Are gehiago, objektu bat sortzen badugu, metodo horretara sartzeak errorea emango du.
Propietate eta metodo estatikoak
class Calculadora {
static VERSION = "1.0";
static sumar(a, b) {
return a + b;
}
}
const resultado = Calculadora.sumar(5, 8);
Printzipioz, ez dugu sistema hau erabiliko, baina garrantzitsua da ezagutzea, JavaScript-ek horrela funtzionatzen duten hainbat klase baititu, hala nola Math.
JavaScript: Document Object Model-en erabilpena
27 DOM-a (Document Object Model)
Nabigatzaile batek web-orri bat kargatzen duenean, ez du zuzenean HTML kodearekin lan egiten. Horren ordez, dokumentua aztertu eta Document Object Model edo, besterik gabe, DOM izeneko barne-errepresentazio bat eraikitzen du.
DOMak HTML elementu guztiak (baita XML eta SVG elementuak ere) JavaScript objektu bihurtzen ditu (beren atributuak dituztenak), eta nodoen zuhaitz baten edo DOM tree baten bidez irudikatzen ditu. DOMa, berez, web API bat eta estandarra da, eta DOMaren bidez JavaScript-ek honako hauek egin ditzake:
- Orrialde baten edukia irakurri.
- Edukia aldatu.
- Estiloak aldatu.
- Elementuak sortu/ezabatu.
- Erabiltzailearen ekintzei erantzun.
Ikus dezagun ondorengo HTMLa eta zer DOM zuhaitz sortzen den.
HTML
<!DOCTYPE html>
<html>
<head>
<title>Ejemplo</title>
</head>
<body>
<h1>Mi página</h1>
<p>Bienvenido.</p>
</body>
</html>
DOMaren ezaugarri garrantzitsuenetako bat edozein unetan alda daitekeela da. Orrialde batek testu bat automatikoki alda dezake, elementu berriak erakutsi edo edukia ezabatu, orria berriro kargatu beharrik gabe. Portaera hori web aplikazio modernoen oinarria da.
Web-orri batean teknologia bakoitzak funtzio desberdina betetzen du.
| Teknologia | Funtzioa |
|---|---|
| HTML | Dokumentuaren egitura definitzen du. |
| CSS | Aurkezpena eta itxura bisuala definitzen ditu. |
| JavaScript | Portaera eta interakzioa gehitzen ditu. |
DOMak JavaScript-ek HTML edukia aldatzeko eta CSS bidez aldaketa bisualak aplikatzeko aukera ematen duen zubia osatzen du. Edozein nabigatzaileren garatzaile-tresnek DOMa ikuskatzeko aukera ematen dute: F12 sakatu eta Elements fitxa (edo Inspector, nabigatzailearen arabera) hautatuz gero, HTML dokumentutik abiatuta sortutako zuhaitz osoa ikus daiteke.
Nabigatzailearen “garatzaile-tresnak” erabiliz DOM zuhaitza ikus dezakegu.
27.1 DOM zuhaitzaren egitura
DOMak elementu guztiak familia-harremanen bidez antolatzen ditu.
Nodo bakoitzak honako hauek izan ditzake:
- Guraso bat (parent): aurreko adibidean <h1>-en gurasoa <body> da.
- Seme bat edo gehiago (children): <body>-ek bi seme ditu.
- Anai-arrebak (siblings): <h1>-ek hierarkia-maila bereko anaia bat du, <p> dena.
Harreman horiek ulertzeak dokumentuan zehar nabigatzea asko errazten du. Elementu bakoitzak zuhaitzaren barruan duen kokapena ezagutzen du, eta horri esker dokumentuaren egitura osoa zeharka daiteke. Antzeko adibide bat fitxategi-sistema baten egitura litzateke: fitxategi bat ausaz aukeratuta, semeak dituen ikus dezakegu (direktorio bat bada), anai-arrebak dituen (bide berean dauden beste fitxategiak) edo guraso-direktoriora igo gaitezkeen.
DOM zuhaitza fitxategi-sistema batekin konparatu dezakegu: elementua ezagututa, beste edozein elementutara joan gaitezke.
27.2 Nodo motak
Normalean HTML elementuekin lan egingo badugu ere, DOMak hainbat nodo mota ditu:
- Dokumentua.
- HTML elementuak.
- Iruzkinak.
- Testua.
Ondorengo adibidean elementua den <p> nodo bat da. "Bienvenido" testuak ere beste nodo bat osatzen du.
HTML
<p>Bienvenido.</p>
27.2.1 Erro-nodoa: document
DOM osoa document izeneko objektu global baten bidez irudikatzen da, eta objektu hori orrialdeko edozein elementutara sartzeko abiapuntua da. Hierarkiako mailarik gorenean dagoen nodoa da, erro-nodoa, “guztien gurasoa”.
Erro-nodo horren barruan, HTML guztiek izango dituzten hainbat propietate daude. Horien artean, honako hauek nabarmendu daitezke:
- head: nodo hau irakurtzeko soilik da eta dokumentuaren <head> itzultzen du.
- body: dokumentuaren gorputza adierazten du, eta bertan izango ditugu elkarreragin nahi dugun nodoak eta elementuak.
- title: uneko dokumentuaren izenburua da; lortu edo aldatu egin dezakegu.
Sortu oinarrizko HTML bat eta lortu document-en azaldutako propietateak. Aldatu orriaren titlea.
29 Edukiaren aldaketa
DOMeko elementu bat aurkitu ondoren, hurrengo urratsa haren edukia aldatzea da. JavaScript-ek hainbat propietate eskaintzen ditu zeregin hori egiteko:
- textContent
- innerHTML
- innerText
Hirurek elementu baten edukia aldatzeko aukera ematen badute ere, haien artean alde garrantzitsuak daude.
29.1 textContent propietatea
textContent propietateak elementu batean dagoen testu guztia lortzeko edo aldatzeko aukera ematen du. Demagun ondorengo HTMLa.
HTML
<h1 id="ti">Hola</h1>
<p id="hola">
Ey <span>Alice</span>
</p>
JavaScript
const ti = document.querySelector("#ti");
console.log(ti.textContent);
ti.textContent = "JavaScript";
Ikus daitekeen bezala, elementuaren testua lortu eta alda dezakegu.
- Zer gertatzen da hola elementuaren testua aldatzen badugu?
- Zer gertatzen da <b>Hola</b>-rekin ordezkatzen badugu?
textContent-ek ez du HTML kodea interpretatzen.
29.2 innerHTML propietatea
innerHTML-ek elementu baten HTML edukia irakurtzeko edo aldatzeko aukera ematen du. Oso erosoa da osagai bat aldatzeko eta HTML berria gehitzeko; arazoa da segurtasun-arazoak sor ditzakeela JavaScript kode maltzurra exekutatuz, sartutako kodea interpretatzen duelako.
HTML
<h1 id="ti">Hola</h1>
<p id="hola">
Ey <span>Alice</span>
</p>
<p id="nuevo"></p>
JavaScript
const h = document.querySelector("#hola");
h.innerHTML = "<strong>Alice</strong>";
const n = document.querySelector("#nuevo");
n.innerHTML = `
<h2>Noticias</h2>
<p>bla bla</p>
`;
- innerHTML erabili bi elementu aldatzeko eta sartu HTML kodea.
- Erabili <img src="img.png" onload="alert('hacked!');">
- Zer gertatzen da azken instrukzio horrekin? (existitzen den irudi bat erabili behar duzu).
innerHTML-ek segurtasun-arazoak sor ditzake, sartutako kodea interpretatzen duelako.
29.3 innerText propietatea
innerText-ek ere testuarekin lan egiten du, baina ikusgai dagoen edukia soilik hartzen du kontuan. Hau da, ezkutatutako (hidden) testua eta estilo-kodea edo <script> etiketetako kodea ez ditu kontuan hartzen. MDNren dokumentazioan adibide bat dago.
- MDN-ren dokumentazioa eta playground erabili innerText zer egiten duen ikusteko.
- Aldatu adibidea innerHTML eta textContent erabil ditzan.
- Zein alde dago haien artean?
30 Elementuen atributuak
HTML elementuek haien ezaugarriak deskribatzen dituzten atributuak dituzte. JavaScript erabiliz, atributu horiek kontsultatu, aldatu, gehitu edo ezabatu ahal izango ditugu.
JavaScript-etik elementuen HTML atributuetara eta DOMeko objektuaren propietateetara sar gaitezke. Printzipioz, nabigatzaileak biak sinkronizatuta mantentzen ditu aldaketak egiten baditugu.
30.1 Atributuak lortu
Elementu batean set eginda dauden atributuen izenak lortu nahi baditugu, getAttributeNames() erabil dezakegu. Metodo horrek izenak dituen array bat itzuliko digu, eta, beraz, aurretik ikusitako begiztetako baten bidez zeharka dezakegu.
Atributu zehatz baten edukia lortu nahi badugu, getAttribute("nombre") erabiliko dugu.
Atributua existitzen ez bada, null itzuliko digu.
HTML
<img src="img.png" id="foto">
<a href="https://kernel.org">
Visitar
</a>
<input type="text">
Atributuak lortu
const imagen = document.querySelector("#foto");
let nombres = imagen.getAttributeNames();
for (let n of nombres){
console.log(n);
imagen.getAttribute(n);
}
//acceder directamente al id
console.log(imagen.id);
Atributuak ezagutzen baditugu, zuzenean objektuaren bidez atzi ditzakegu.
30.2 Atributuak aldatu
Elementu baten atributuak alda ditzakegu edo atributu berriak sor ditzakegu setAttribute() funtzioa erabiliz.
Atributuak aldatu
const enlace = document.querySelector("a");
//modifica el atributo HTML
enlace.setAttribute("target","_blank");
//modifica el objeto DOM
enlace.href="https://www.google.com";
30.3 Atributu pertsonalizatuak sortu
Nahiz eta ezerk ez eragotzi nahi dugun izenarekin atributu pertsonalizatuak sortzea, jardunbide egokiek eta estandarrak adierazten digute data--rekin hasi behar dugula haien izena. Dokumentazioak adierazten digu horrela informazio hori HTMLaren eta DOMaren artean trukatuko dela.
Atributu pertsonalizatuak
const enlace = document.querySelector("a");
enlace.setAttribute("data-grado","DAW");
enlace.setAttribute("data-curso",2);
//obtener todos los atributos personalizados
console.log(enlace.dataset);
//acceder a un atributo personalizado concreto
console.log(enlace.dataset.grado);
console.log(enlace.dataset.curso);
Atributu horiek oso erabilgarriak dira elementu batekin lotutako informazioa gordetzeko.
30.4 Atributuak ezabatu
Sortu ditzakegun bezala, atributu zehatz bat ere ezaba dezakegu.
Atributuak ezabatu
enlace.removeAttribute("target");
30.5 Existitzen den egiaztatu
Atributu bat existitzen den egiaztatzeko, hasAttribute() erabil dezakegu, eta balio boolear bat itzuliko digu.
Existitzen den egiaztatu
console.log(enlace.hasAttribute("href"));
Erabili atributuei buruz ikusitako funtzioak.
31 CSS klaseen kudeaketa
CSS klaseek elementu baten itxura bisuala aldatzeko aukera ematen dute. JavaScript-ek klaseak dinamikoki gehitu, ezabatu edo txandakatu ditzake. Horrela, elementuak dinamikoki erakutsi/ezkutatu, informazioa nabarmendu, koloreak aldatu, erabiltzailearen ekintzen arabera interfazea aldatu eta abar egin dezakegu.
Klaseekin edozein ekintza egiteko, classList propietatea erabili behar da. Propietate horrek hainbat funtzio ditu, eta jarraian ikusiko ditugu.
classList, funtzio barik, klaseen array bat itzultzen du.
Hurrengo adibideetan ondorengo kodea erabiliko da:
HTML
<p id="mensaje">
Bienvenido
</p>
CSS
.destacado {
color: red;
font-weight: bold;
}
.italica {
font-style: italic;
}
31.1 Klaseak gehitu
Elementu zehatz bati klase bat gehitu nahi badiogu, classList.add() erabil dezakegu.
Klaseak gehitu
const mensaje = document.querySelector("#mensaje");
mensaje.classList.add("destacado");
31.2 Klase bat txandakatu
classList.toggle() metodoak klasea gehitzen du elementuak ez badu, eta badu, ezabatu egiten du.
Klase bat txandakatu
const mensaje = document.querySelector("#mensaje");
mensaje.classList.toggle("italica");
31.3 Klase bat existitzen den egiaztatu
Elementu batek klase bat duen jakiteko, classList.contains() funtzioa erabil dezakegu; funtzio horrek balio boolear bat itzultzen du.
Egiaztatu klasea dagoen
const mensaje = document.querySelector("#mensaje");
console.log(mensaje.classList.contains("italica"));
31.4 Klase bat ordezkatu
Klase bat beste batekin aldatu nahi badugu, classList.replace() funtzioa dugu.
Klasea ordezkatu
const mensaje = document.querySelector("#mensaje");
mensaje.classList.replace(
"destacado", // reemplaza esta clase
"normal" // por esta otra
);
31.5 Hainbat klase gehitu
Hainbat klase banan-banan gehitu beharrean, classList.add() erabil dezakegu.
Klasea gehitu
const mensaje = document.querySelector("#mensaje");
mensaje.classList.add(
"rojo",
"grande",
"centrado"
);
31.6 className atributua
className atributuak bi funtzio ditu:
- Dauden klase guztiak itzultzen dizkigu.
- Klase guztiak aldatzeko aukera ematen digu.
Klase guztiak aldatu
const mensaje = document.querySelector("#mensaje");
// obtener todas las clases
console.log(mensaje.className);
mensaje.className = "destacado italica";
31.7 Laburpena
| Metodoa | Funtzioa |
|---|---|
| classList | Klaseen array bat itzultzen du. |
| classList.add() | Klase bat gehitzen du. |
| classList.remove() | Klase bat ezabatzen du. |
| classList.toggle() | Klase bat gehitu edo ezabatzen du. |
| classList.contains() | Klase bat existitzen den egiaztatzen du. |
| classList.replace() | Klase bat beste batekin ordezkatzen du. |
| className | Klase guztiak lortzen ditu edo ordezkatzen ditu. |
Erabili aurreko funtzioak elementu baten klaseak aldatzeko.
32 DOMeko elementuen kudeaketa
Orain arte, orrian lehendik zeuden elementuak aldatzen ikasi dugu. Normalean, web-aplikazio batean elementu berriak sortu, edozein kokapenetan txertatu edo beharrezkoak ez direnean ezabatu ere nahi izango dugu. Adibidez:
- Zereginen zerrendari elementu berri bat gehitzea.
- Taula batean errenkada bat sortzea.
- Jakinarazpen bat erakustea.
- Mezu bat ezabatzea.
- API batetik lortutako informazioarekin txartel bat sortzea.
JavaScript-ek hainbat metodo eskaintzen ditu zeregin horiek egiteko.
32.1 Elementu bat sortzea
Elementu bat sortzeko createElement() funtzioa erabiltzen da. Demagun paragrafo bat sortu nahi dugula. Prozesuak hainbat urrats ditu:
- Elementua sortzea: Une honetan elementua oraindik ez da orrian agertzen, elementua sortu egin delako eta memorian soilik existitzen delako.
- Edukia gehitzea: Sortu ondoren, edukia gehitu edo haren propietateak alda ditzakegu.
- Dokumentuan txertatzea: Nabigatzaileak erakuts dezan, DOMean txertatu behar dugu. Elementua non txertatu nahi dugun pentsatu beharko dugu; beste elementu baten barruan edo body-n izan daiteke.
Elementu bat gehitu
// crear elemento
const parrafo = document.createElement("p");
// añadir contenido
parrafo.textContent = "Hola mundo";
// modificar sus propiedades
parrafo.className = "importante";
// insertarlo en el documento
document.body.append(parrafo);
Kasu honetan paragrafo bat sortu da, edukia eman zaio, klase berri bat gehitu zaio eta body-aren amaieran gehitu da.
Adibide konplexuago bat egingo dugu, elementuen egitura guztiz berria sortuz:
Elementuak sortu
const tarjeta = document.createElement("div");
const titulo = document.createElement("h2");
const descripcion = document.createElement("p");
titulo.textContent = "JavaScript";
descripcion.textContent = "Creado en...";
tarjeta.append(titulo);
tarjeta.append(descripcion);
document.body.append(tarjeta);
HTML generado
<body>
<!-- ... -->
<div>
<h2>JavaScript</h2>
<p>Creado en...</p>
</div>
</body>
32.1.1 Zein metodo erabili?
Aurretik innerHTML metodoa ikusi dugu, eta orain createElement() metodoa. Bi teknikak baliagarriak badira ere, alde garrantzitsuak dituzte.
| createElement() | innerHTML |
|---|---|
| DOMeko objektuak sortzen ditu. | HTML kodea txertatzen du. |
| Seguruagoa da. | Segurtasun-arriskuak sor ditzake. |
| Oso egokia da eduki dinamikoa sortzeko. | Erosoa da HTML kopuru handia sortzeko. |
| Elementu bakoitza banaka aldatzeko aukera ematen du. | Elementuaren edukia ordezkatzen du. |
Aplikazio modernoetan createElement() erabili behar da elementuak datuetatik abiatuta dinamikoki sortzen direnean.
Aplikazio modernoetan createElement() erabili behar da.
32.1.2 Sortutako elementua txertatzea
Elementu berri bat (edo elementuen zuhaitz txiki bat) sortzen dugunean, non txertatu erabaki behar dugu. Horretarako, hainbat metodo ditugu:
| Metodoa | Non? |
|---|---|
| append() | Azken seme-alaba gisa txertatzen du. |
| prepend() | Hasieran txertatzen du, lehen seme-alaba gisa. |
| before() | Elementuaren aurretik txertatzen du. |
| after() | Elementuaren ondoren txertatzen du. |
HTML
<h1>Comprar</h1>
<ul id="lista">
<li>Tomates</li>
</ul>
Javascript
const lista = document.querySelector("#lista");
const pan = document.createElement("li");
pan.textContent = "Pan";
lista.append(pan);
const arroz = document.createElement("li");
arroz.textContent = "Arroz";
lista.prepend(arroz);
const p = document.createElement("p");
p.textContent = "Hay que comprar:"
lista.before(p);
const fin = document.createElement("p");
fin.textContent = "No te olvides de nada!"
lista.after(fin);
32.1.3 Elementu bat mugitzea
DOMaren xehetasun garrantzitsu bat da elementu bat behin bakarrik existitu daitekeela. Elementu bat beste kokapen batean txertatzen badugu, nabigatzaileak ez du kopiarik sortzen; besterik gabe, mugitu egiten du.
Javascript
const lista = document.querySelector("#lista");
const elemento = document.createElement("li");
elemento.textContent = "Pan";
lista.prepend(elemento);
elemento.textContent = "Arroz";
lista.append(elemento);
Bigarren instrukzioaren ondoren, elementua zerrendaren amaieran soilik egongo da.
32.2 Elementu bat ezabatzea
Elementu bat ezabatu nahi badugu, zeregin erraza da. Elementu zehatza hautatu ondoren, remove() funtzioa erabiltzen dugu, eta DOMetik desagertuko da.
Javascript
const lista = document.querySelector("#lista");
lista.remove();
32.3 Elementu bat ordezkatzea
Elementu baten edukia beste batekin ere ordezka daiteke.
HTML
<p id="mensaje">
Texto antiguo
</p>
Javascript
const nuevo = document.createElement("h2");
nuevo.textContent = "Nuevo mensaje";
const antiguo = document.querySelector("#mensaje");
antiguo.replaceWith(nuevo);
32.4 Elementu bat hustea
Elementu baten barruko edukia soilik ezabatu nahi badugu (elementua bera ezabatu gabe), honako hau egin dezakegu:
Javascript
lista.textContent = "";
// alternativa
lista.innerHTML = "";
Zeharkatu osagaien array bat eta gehitu osagai berriak <li> motako elementuak sortuz, zerrendaren hasieran eta, ondoren, amaieran txertatuz.
32.5 Txertatzeak optimizatzea DocumentFragment bidez
Aurreko adibideetan elementuak sortu eta zuzenean DOMean txertatu ditugu. Kode-adibide horiek behar bezala funtzionatzen dute eta guztiz baliagarriak dira, baina elementu kopurua oso handia denean, eraginkortasun txikia izan dezakete.
Elementu berri bat txertatzen den bakoitzean, nabigatzaileak DOM zuhaitza eguneratu behar du eta, kasu askotan, orriaren diseinua berriro kalkulatu behar du.
Ehunka edo milaka txertatze jarraian egiten direnean, prozesu horrek aplikazioaren errendimenduan eragina izan dezake. Arazo hori konpontzeko, JavaScript-ek DocumentFragment() objektua eskaintzen du.
DocumentFragment() gurasorik ez duen aldi baterako edukiontzi bat da, Document motako objektu arinago bat memorian erabat eraikitzeko aukera ematen duena. Elementuak sortu eta fragmentuan gehitzen dira, baina oraindik ez dira DOM dokumentu nagusiaren parte. Amaitutakoan, fragmentuaren eduki osoa DOMean txertatzen da eragiketa bakar baten bidez.
32.5.1 Fragmentu bat sortu
Fragmentu bat createDocumentFragment() bidez sortzen da. Une horretatik aurrera, DOMeko beste edozein elementu balitz bezala erabil daiteke.
Fragmentua sortu
const fragmento = document.createDocumentFragment();
32.5.2 Elementuak gehitu
Demagun zerrenda huts bat dugula eta bertan hainbat elementu gehitu nahi ditugula. Aurretik banan-banan nola gehitu ikusi dugu. Kasu honetan, ordea,
Elementuak fragmentuari gehitu
const lenguajes = [
"HTML",
"CSS",
"JavaScript",
"TypeScript",
"Vue"
];
for (const lenguaje of lenguajes) {
const elemento = document.createElement("li");
elemento.textContent = lenguaje;
fragmento.append(elemento);
}
Une honetan orriak berdin-berdin jarraitzen du. Elementuak oraindik ez dira erakusten, DOMean txertatu ez direlako.
32.5.3 Fragmentua txertatzea
Elementu guztiak fragmentuari gehitzen amaitu ondoren, DOMean gehitu behar dugu.
HTML
<h1>Lenguajes</h1>
<ul id="lista">
</ul>
Javascript
const lista = document.querySelector("#lista");
lista.append(fragmento);
Hori egindakoan, erabiltzaileak azken emaitza ikusiko du. Xehetasun garrantzitsu bat da fragmentua ez dela beste nodo bat balitz bezala txertatzen. Fragmentua hutsik geratzen da, eta, behar izanez gero, berriro erabil daiteke.
32.5.4 Zergatik da eraginkorragoa?
Demagun 1000 elementu txertatu nahi ditugula. Prozesua honakoa izango litzateke:
Gertaerak (events)
33 Sarrera
Orain arte DOMeko elementuetara sartzen eta JavaScript bidez aldatzen ikasi dugu. Hala ere, web-orri bat oraindik ez da interaktiboa, ohikoa baita erabiltzaileak egindako ekintzei erantzutea:
- Botoi batean sakatzea.
- Testu-koadro batean idaztea.
- Aukera bat hautatzea.
- Sagua mugitzea.
- Tekla bat sakatzea.
- Elementu bat arrastatzea.
Ekintza horiei gertaera deitzen zaie. Horiei esker, JavaScript-ek kodea ekintza jakin bat gertatzen den unean bertan exekuta dezake. Gertaerak honako hauek eragin ditzakete:
- Erabiltzaileak.
- Nabigatzaileak.
- HTML dokumentuak berak.
Existitzen diren gertaera guztien artean (elementuaren, document, …) honako hauek nabarmendu ditzakegu, erabilienetakoak baitira:
| Gertaera | Ekintza |
|---|---|
| click | Erabiltzaileak elementu batean sakatzen du. |
| dblclick | Klik bikoitza. |
| input | Testu-eremu baten edukia aldatzen da. |
| change | Inprimaki bateko aldaketa amaitzen da. |
| submit | Inprimaki bat bidaltzen da. |
| keydown | Tekla bat sakatzen da. |
| keyup | Tekla bat askatzen da. |
| mouseenter | Sagua elementu batean sartzen da. |
| mouseleave | Sagua elementutik ateratzen da. |
| load | Orria kargatzen amaitzen da. |
33.1 Gertaerek gidatutako programazioa
Web-aplikazio modernoek gertaerek gidatutako programazioa izeneko eredu baten bidez funtzionatzen dute. Instrukzioak bata bestearen atzetik exekutatu eta programa amaitu arte itxaron beharrean, JavaScript-ek gertaeraren bat gertatu zain egoten da.
Gertaera gertatzen denean, hari lotutako kodea exekutatzen du eta, ondoren, hurrengo gertaeraren zain geratzen da berriro. Portaera horri esker, orriak aktibo eta interaktibo iraun dezake erabiltzaileak erabiltzen duen bitartean.
Egia esan, ez da JavaScript erabiltzailearen ekintzak zuzenean detektatzen dituena; nabigatzailea da gertatzen dena etengabe behatzen duena. Gertaera bat detektatzen duenean, JavaScript-en exekuzio-motorrari jakinarazten dio dagokion funtzioa exekuta dezan.
34 Erregistratu gertaerak: addEventListener()
JavaScript-ek gertaera bati erantzun diezaion, beharrezkoa da gertaera hori erregistratzea. Gaur egun, gomendatutako modua addEventListener() metodoa erabiltzea da (2015etik dago erabilgarri). Metodo horrek edozein gertaerari funtzio bat lotzeko aukera ematen du; beraz, gutxienez bi parametro nagusi jasotzen ditu.
- Gertaeraren izena.
- Gertaera gertatzen denean exekutatuko den funtzioa.
HTML
<button id="boton">
Pulsar
</button>
<ul id="lista"></ul>
JavaScript
const boton = document.querySelector("#boton");
boton.addEventListener(
"click",
function () {
console.log("Botón pulsado.");
const e = document.createElement("li");
e.textContent = "elemento";
const l = document.getElementById("lista");
l.append(e);
}
);
Adibide honekin, gertaera bat sortzea eta aurretik ikusitako elementuen sorrera lotu ditugu. Botoian sakatzean, zerrendari gehituko zaion elementu bat sortzen da, eta, gainera, mezu bat erakusten da kontsolan. Dokumentazioan addEventListener()-ek dituen aukera guztiak ikus daitezke.
Kasu honetan, funtzioa (modu klasikoan) gertaeraren barruan sortu dugu, baina gezi-funtzio bat erabil dezakegu edo lehendik dagoen funtzio bati deitu:
Gezi funtzioa
boton.addEventListener(
"click",
() => {
console.log("Botón pulsado.");
}
);
Funtzioari deitu
boton.addEventListener(
"click",
nuevoElemento
);
Erabili aurreko adibidea eta sortu click gertaerak abiaraziko dituzten 3 botoi: bata funtzio oso batekin, bestea gezi-funtzio batekin eta hirugarrena lehendik dagoen funtzio bati deituz.
34.1 Elementu bat hainbat gertaerarekin
Elementu berak hainbat gertaerari erantzun diezaioke.
Elementu hainbat gertaerarekin
boton.addEventListener(
"mouseenter",
() => { console.log("Ratón encima.");}
);
boton.addEventListener(
"mouseleave",
() => { console.log("Ratón sale del botón.");}
);
34.2 Gertaera bererako hainbat funtzio
Zenbait egoeratan gertaera bererako bi funtzio edo gehiago izan nahi ditugu; beraz, hainbat funtzio erregistra ditzakegu gertaera bererako.
Funtzio desberdin gertaera berdin batekin
boton.addEventListener(
"click",
() => console.log("Primera")
);
boton.addEventListener(
"click",
() => console.log("Segunda")
);
Botoian klik egitean, bi funtzioak exekutatuko dira.
34.3 Zergatik erabili addEventListener()?
HTML eta JavaScript bidez gertaerak sortzeko, honako modu hauek ere erabil daitezke:
HTMLn inline funtzioa
<!-- añadir función en HTML-->
<button onclick="saludar()">
Gehitu gertaera elementuari
// añadir evento al elemento
boton.onclick = function (){
console.log("Hola");
}
boton.onclick = function (){
console.log("Adios");
}
Zer gertatzen da botoian sakatzean? Hiru funtzioetatik zein exekutatzen da?
Aurreko ariketa abiapuntutzat hartuta:
- Gehitu mouseenter eta mouseleave gertaerak button1 botoiari.
- Gehitu HTMLko onclick funtzio inline bat button1 botoiari.
- Gehitu bi onclick gertaera button1 botoiaren elementuari JavaScript bidez.
Zer exekutatzen da azkenean button1 botoian klik egitean?
Ariketa eginda egiaztatu ahal izan den bezala, addEventListener() erabiltzeak hainbat abantaila ditu metodo “zaharren” aldean:
- HTMLa eta JavaScript bereizteak kodearen mantentzea errazten du.
- Gertaera bererako hainbat kudeatzaile erregistratzeko aukera ematen du.
- Inline metodoak funtzio bakarra gehitzeko aukera ematen du.
- Elementu bati gertaera bat gehitzean, aurretik idatzitako kodea gainidazten ez dela ziurtatzen dugu.
- addEventListener()-ek parametro gehiago gehitzeko aukera ematen du, gertaeraren hedapena kontrolatzeko.
Beti addEventListener() erabiltzea gomendatzen da.
34.4 Gertaerak removeEventListener() bidez ezabatzea
Orain arte funtzio bat gertaera bati lotzen ikasi dugu, baina zenbait egoeratan gertaera bat ezabatzea ere beharrezkoa izan daiteke, exekutatzen jarrai ez dezan. Horretarako, JavaScript-ek removeEventListener() metodoa eskaintzen du.
Gertaera bat ezabatzea erabilgarria da, besteak beste, honako egoera hauetan:
- Ekintza bat hainbat aldiz exekuta dadin saihestea.
- Jada erabiltzen ez diren elementuetako gertaerak ezabatzea.
- Aplikazio konplexuen errendimendua hobetzea.
Ondorengo kodeak adibide gisa balio du: Gertaera desaktibatu botoian sakatzean, botoi nagusiak click gertaerari erantzuteari utziko dio.
HTML
<button id="boton">
Pulsar
</button>
<button id="quitar">
Quitar evento
</button>
Gertaera kendu
const boton = document.querySelector("#boton");
const desactivar = document.querySelector("#quitar");
function saludar() {
console.log("Hola");
}
boton.addEventListener("click", saludar);
desactivar.addEventListener("click", () => {
boton.removeEventListener("click", saludar);
});
removeEventListener() erabiltzeak lehendik dagoen funtzio baten erreferentzia adierazten denean baino ez du funtzionatzen; beraz, ez luke balio funtzio inline batekin edo gezi-funtzio batekin.
Erabili removeEventListener() aurretik sortutako gertaera bat ezabatzeko.
34.5 Funtzioaren aukerak
Ikusitako parametroez gain, gertaera-mota eta funtzioa, addEventListener()-ek aukerako parametroak jaso ditzake. Parametro horiek honela bereizten dira:
- options: event listener-aren ezaugarriak zehazten dituen objektua. Eskuragarri dauden aukeren artean honako hauek daude:
- once: balio boolearra; true bada, automatikoki ezabatzen da deitu ondoren. Aurretik ikusitako removeEventListener() erabiltzeko alternatiba da.
- signal: seinale bat lotzeko aukera ematen du.
35 Event objektua
Gertaera bat gertatzen denean, nabigatzaileak automatikoki objektu bat sortzen du, gertaerarekin lotutako informazio guztia duena. Objektu horri Event deitzen zaio. JavaScript-ek automatikoki pasa diezaioke argumentu gisa gertaera kudeatzen duen funtzioari. Funtzioari pasatzen zaion aldagaiaren izena normalean “event""” edo “e""” izaten da, laburtzeko.
Gertaeraren data ikusi
boton.addEventListener(
"click",
(event) => {
console.log(event);
}
);
Gertaeraren data ikusi
boton.addEventListener(
"click",
(e) => {
console.log(e);
}
);
Erabiltzaileak klik egiten duen bakoitzean, nabigatzaileak informazio ugari duen objektu bat erakutsiko du.
35.1 Event-en propietateak
Event objektuak dozenaka propietate eta metodo ditu, baina praktikan arazo jakin bat konpontzeko beharrezkoak direnak baino ez dira erabiltzen. Adibide batzuk honako atributu hauek dira:
- type: gertatu den gertaera-mota adierazten du.
- target: gertaera sortu duen elementua.
- currentTarget: addEventListener() erregistratuta duen elementua adierazten du. Aurreko atributuarekin bat etor daitekeen arren, ez da beti horrela izaten, target gertaera erregistratuta duen elementuaren seme-alaba izan baitaiteke.
- clientX eta clientY: saguaren koordenatuak.
- key eta code: sortutako tekla eta teklatuaren tekla fisikoa adierazten dituzte.
35.2 Event-en oinarritutako interfazeak
Gertaera guztiek Event objektu bat sortzen badute ere, hainbat interfaze espezializatu daude. Horietako batzuk:
MouseEvent: dokumentazioak dioen bezala, erabiltzaileak “seinalatze-gailu batekin” (sagua, adibidez) elkarreragiten duenean gertatzen diren gertaerak.
KeyboardEvent: teklatuarekiko elkarreragin-gertaerak.
SubmitEvent: gertaera hau inprimaki baten submit ekintza deitzen denean aktibatzen da.
InputEvent: edita daitezkeen edukietan gertatzen diren aldaketekin lan egiten duten gertaerak.
FocusEvent: “fokuarekin” lotutako gertaerak.
TouchEvent: ukipen-pantailetarako edo trackpad-etarako.
DragEvent: drag & drop elkarreragina adierazten duten gertaerak.
GamepadEvent: joko-kontrolagailuen APIrako interfazea.
36 Gertaeren adibideak
Jarraian, ohiko moduan erabiltzen diren hainbat gertaeren adibide ikusiko ditugu.
36.1 Saguaren gertaerak
Orain arte ikusitako adibide guztiek click gertaera hartu dute kontuan. Saguari dagokio eta MouseEvent bat sortzen du. Jarraian, adibide berri bat ikusiko dugu, Event-en propietateak erabiliz:
HTML
<button>Rojo</button>
<button>Verde</button>
<button>Azul</button>
Elementuari gertaera gehitu
const botones = document.querySelectorAll("button");
for (const boton of botones) {
boton.addEventListener("click", (e) => {
console.log(e.target.textContent);
console.log(`X,Y: ${e.clientX},${e.clientY}`);
});
}
- Sortu hiru botoi Event objektuaren informazioa lortzeko gertaerekin.
- Sortu div elementu bat gertaera batekin. div horrek, aldi berean, beste bi div elementu izan behar ditu barruan. Egiaztatu target eta currentTarget arteko aldea.
36.2 Teklatuaren gertaerak
Erabiltzaileak tekla bat sakatzen duenean, KeyboardEvent objektu bat sortzen da. Gertaera bat sor dezakegu document-en, keylogger gisa funtziona dezan:
Teklatuaren gertaerak
document.addEventListener("keydown", (e) => {
console.log(`${e.key} y ${e.code}`);
});
Sortu Konami kodea (https://en.wikipedia.org/wiki/Konami_Code) sartzean alerta bat sortzen duen web-orri bat.
36.3 Sarrerako gertaerak
Inprimakietako sarrera elementuek (<input>) gertaera espezifikoak sortzen dituzte editatzen direnean edo fokua lortzen dutenean.
HTML
<form id="form">
<input id="nombre">
</form>
<pre id="output"></pre>
Sarrerako gertaerak
const form = document.querySelector("#form");
const nombre = document.querySelector("#nombre");
form.addEventListener("input", (e) => {
console.log(e.target.value);
});
nombre.addEventListener("focus", (e) => {
console.log(e.target.value);
});
Erabiltzaileak letra bat idazten duen bakoitzean, testu-koadroaren uneko edukia agertuko da, eta baita testuak fokua jasotzen duenean ere.
Sortu input, range eta textarea bat dituen inprimaki bat. Inprimakiak fokua nork duen eta aldaketa bat egitean duen balioa logeatu behar ditu.
36.4 Inprimakiaren/bidalketaren gertaerak
Inprimakiek gertaera bat ere sortzen dute bidaltzen saiatzen direnean, submit gertaera gertatzean.
Añadir evento al formulario
const formulario = document.querySelector("form");
formulario.addEventListener("submit", (evento) => {
console.log("Formulario enviado");
});
37 Portaera lehenetsia saihestu
Elementu batzuek portaera lehenetsi bat dute: esteka batek beste orri bat irekitzea edo inprimaki bat zerbitzarira bidaltzea, adibidez. Batzuetan interesgarria da portaera hori saihestea. Horretarako, preventDefault() funtzioa dugu.
Portaera lehenetsia saihestu
formulario.addEventListener("submit", (evento) => {
evento.preventDefault();
console.log("Envío cancelado.");
});
38 Gertaeraren hedapena gelditu
Gertaerak DOM zuhaitzean behetik gora hedatzen dira. Edukiontzi batek beste elementu bat duenean barruan eta biek gertaerak entzuten dituztenean, elementu barrukoenean gertaera bat abiaraztean, elementu hori duen edukiontziak ere jasoko du gertaera. Hedapen hori geldiarazteko, stopPropagation() funtzioa dago.
Gertaeraren hedapena gelditu
formulario.addEventListener("submit", (evento) => {
evento.stopPropagation();
});
- Sortu div bat, eta haren barruan beste div bat. Biek click gertaera jaso dezakete.
- Erabili checkbox bat gertaeraren hedapena gelditu nahi duzun kontrolatzeko.
- Egin klik bi egoeretan: zer gertatzen da?
Formularioak eta balidazioa
39 Sarrera
Orain arte JavaScript erabiliz web-orri dinamikoak sortzen, DOMa manipulatzen eta gertaeren bidez erabiltzailearen ekintzei erantzuten ikasi dugu. Hala ere, web-aplikazio gehienek erabiltzaileak informazioa sartzeko aukera behar dute.
Adibidez:
- Saioa hastea.
- Erregistratzea.
- Produktuak bilatzea.
- Mezuak bidaltzea.
- Eskaerak egitea.
- Hobespenak konfiguratzea.
Informazio hori guztia inprimakien/formularioen bidez jasotzen da. Inprimakiak erabiltzaileari web-orri batean informazioa sartzeko aukera ematen dioten kontrolen multzoa dira.
Sartutako datuak hainbat helburutarako erabil daitezke:
- Zerbitzari batera bidaltzeko.
- JavaScript bidez prozesatzeko.
- Nabigatzailean gordetzeko.
- Informazioa iragazteko edo bilatzeko erabiltzeko.
Inprimakiak web-aplikazioen garapenean gehien erabiltzen diren elementuetako bat dira.
40 <form> elementua
Inprimaki baten kontrol guztiak normalean <form> elementu baten barruan taldekatzen dira. Elementu horrek erlazionatutako kontrol guztien edukiontzi gisa jokatzen du.
Oinarrizko formularioa
<form>
<label for="nombre">Nombre</label>
<input type="text" id="nombre" name="nombre">
<button type="submit">Login</button>
</form>
Tradizionalki, erabiltzaileak bidalketa-botoia sakatzen duenean, nabigatzaileak inprimakiko datu guztiak bildu eta zerbitzarira bidaltzen ditu. Gaur egun, JavaScript-ek esku hartu ohi du datuak zuzenak direla egiaztatzeko.
Garrantzitsua da beti balidazioa backend-ean ere egitea.
40.1 Inprimakiaren atributu nagusiak
<form> elementuak atributu ugari ditu. Garrantzitsuenak hauek dira.
| Atributua | Deskribapena |
|---|---|
| action | Datuak bidaliko diren zerbitzariaren helbidea. |
| method | Erabilitako HTTP metodoa (GET informazioa lortzeko edo POST datuak bidaltzeko). |
| autocomplete | Nabigatzailearen autobetetze-funtzioa aktibatzen (=on) edo desaktibatzen (=off) du. |
| novalidate | HTML5en balidazio automatikoa desaktibatzen du. |
| name | Inprimakiaren izena. Gaur egun gehiago erabiltzen da id. |
Formularioa atributuekin
<form action="/login" method="post" autcomplete="on" name="registro">
<label for="nombre">Nombre</label>
<input type="text" id="nombre" name="nombre">
<button type="submit">Login</button>
</form>
Aldatu inprimakiaren atributuak eta egiaztatu zer gertatzen den.
40.2 Inprimakiaren barruko kontrolak
Inprimaki batek hainbat kontrol-mota izan ditzake, hala nola <input>, eta horietako bakoitza informazio-mota jakin bat sartzeko diseinatuta dago. Garrantzitsua da egokiak aukeratzea, aplikazioaren erabilgarritasuna erraztuko baitute eta, gainera, datuen balidazioa erraztuko baitute. Honako hauek izan daitezke:
- Testu-koadroak.
- Pasahitzak.
- Egiaztapen-laukiak.
- Aukera-botoiak.
- Goitibeherako zerrendak.
- Testu-eremuak.
- Botoiak.
40.2.1 Kontroletako name atributua
Kontrol guztiek name atributu bat izan behar dute. Atributu hori izango da inprimakia bidaltzean zerbitzarira bidaliko den identifikatzailea.
Formularioa atributuekin
<form action="/login" method="post" autcomplete="on" name="registro">
<label for="nombre">Nombre</label>
<input type="text" id="nombre" name="name">
<button type="submit">Login</button>
</form>
Aurreko adibidean ikus dezakegu input motako text kontrolak beste bi atributu dituela, eta izen desberdinak eman zaizkie bereizteko:
- id: orain arte ikusi dugun HTML identifikatzaile bakarra da.
- name: botoia sakatzean zerbitzarira bidaliko den eremuaren izena da.
Aldatu id eta name atributuak eta aztertu aldaketak.
40.2.2 Testu-eremuak
Testu-kontrolek karaktere-kateak sartzeko aukera ematen dute. Hainbat atributu dituzte, baina garrantzitsuena type da:
- type: Testu-eremuaren mota adierazten du. Mota jakinaren arabera, testua sartzea erraztu dezake.
- text: Testu-eremu arrunta.
- password: Pasahitzetarako; nabigatzaileak sartutako karaktereak ezkutatzen ditu, baina ez da zifratzen.
- email: HTML5ek automatikoki egiaztatuko du formatuak email baten antza duen.
- url: Web-helbideak sartzeko aukera ematen du.
- tel: Ez du formatua automatikoki balidatzen, baina datua gailu mugikorretan sartzea errazten du.
- search: Nabigatzaile batzuek edukia ezabatzeko botoiak dituzte.
- minlength: string-aren gutxieneko luzera.
- maxlength: Eduki behar duen gehieneko luzera. Muga horretara iritsiz gero, ezin da gehiago idatzi.
- pattern: Sartutako testuak bete behar duen adierazpen erregularra idazteko aukera ematen du.
- placeholder: Lehenespenez agertzen den testua da, baina erabiltzailea idazten hasten denean desagertu egiten da.
- readonly: Balio boolearra da; atributua badago, eremua ezin da editatu.
- size: Testu-eremuaren tamaina.
Testu eremuak
<label for="nombre">Nombre</label>
<input type="text" name="nombre">
<label for="password">Password</label>
<input type="password" name="password" min=6 max=12>
<label for="email">email</label>
<input type="email" name="email" placeholder="hola@example.com">
40.2.3 Zenbakizko eremuak
Zenbakizko eremuak testu-eremuen antzekoak dira, baina zenbakietarako soilik, eta normalean handitzeko edo txikitzeko botoiak izaten dituzte. type="number" gisa ezarri behar da, eta berezko atributuak ere baditu:
- max: Onartutako gehieneko zenbakia.
- min: Onartutako gutxieneko zenbakia.
- step: Botoiekin handitzeko edo txikitzeko erabiltzen den kopurua.
Zenbaki eremuak
<label for="number">number</label>
<input type="number" name="number" min=5>
<label for="number2">number2</label>
<input type="number" name="number2" min=6 max=50 step=2>
40.2.4 Ordu/data eremuak
Orduak eta/edo datak adierazteko erabiltzen diren eremu espezifiko batzuk daude.
- type: Eremu-mota adierazten du.
- date: Datetarako eremua.
- datetime-local: Tokiko data eta ordurako.
- month: Urte jakin bateko hilabete bat hautatzeko.
- time: Ordua soilik hautatzeko.
- week: Astea soilik hautatzeko.
- max: Mota bakoitzaren arabera, onartutako gehieneko ordua/data adieraziko du. Formatua motaren araberakoa izango da.
- min: Mota bakoitzaren arabera, onartutako gutxieneko ordua/data adieraziko du. Formatua motaren araberakoa izango da.
Ordu/data eremuak
<label for="number">date</label>
<input type="date" name="date">
<label for="datetime-local">datetime-local</label>
<input type="datetime-local" name="datdatetime-locale">
<label for="month">month</label>
<input type="month" name="month">
<label for="time">time</label>
<input type="time" name="time">
<label for="week">week</label>
<input type="week" name="week">
40.2.5 Tarte-eremuak
Datu-tarte baten barruan balio bat hautatzeko graduatzaile motako eremuak dira. type="range" motakoak dira, eta max, min eta step atributuak ere onartzen dituzte.
Tarte-eremuak
<label for="range">range</label>
<input type="range" name="range">
<label for="range2">range2</label>
<input type="range" name="range2" min=0 max=30 step=2>
40.2.6 Lauki eta aukera-eremuak
Hainbat aukera aldi berean edo hainbat aukeren artean aukera bakarra hautatzeko aukera ematen dute:
- type: Eremu-mota adierazten du.
- checked: Aukera hautatuta dagoela adierazten duen balio boolearra.
name bera partekatzen duten laukiak talde berekoak dira.
Lauki eta aukera-eremuak
<fieldset>
<legend>Choose your interests:</legend>
<div>
<input type="checkbox" id="coding" name="interest" value="coding" checked />
<label for="coding">Coding</label>
</div>
<div>
<input type="checkbox" id="music" name="interest" value="music" />
<label for="music">Music</label>
</div>
</fieldset>
<fieldset>
<legend>Please select your preferred contact method:</legend>
<div>
<input type="radio" id="contactChoice1" name="contact" value="email" />
<label for="contactChoice1">Email</label>
<input type="radio" id="contactChoice2" name="contact" value="phone" />
<label for="contactChoice2">Phone</label>
<input type="radio" id="contactChoice3" name="contact" value="mail" />
<label for="contactChoice3">Mail</label>
</div>
</fieldset>
40.2.7 Zabalgarri zerrendak
Ohikoa da inprimaki batean hainbat aukera dituen goitibeherako zerrendak egotea:
Zabalgarri zerrendak
<label for="hr-select">Your favorite food</label> <br />
<select name="foods" id="hr-select">
<option value="">Choose a food</option>
<hr />
<optgroup label="Fruit">
<option value="apple">Apples</option>
<option value="banana">Bananas</option>
<option value="cherry">Cherries</option>
<option value="damson">Damsons</option>
</optgroup>
<hr />
<optgroup label="Fish">
<option value="cod">Cod</option>
<option value="haddock">Haddock</option>
<option value="salmon">Salmon</option>
<option value="turbot">Turbot</option>
</optgroup>
</select>
40.2.8 Beste kontrol batzuk
Inprimakiek beste kontrol batzuk ere badituzte. Horietako batzuk ez dira hain ohikoak, baina beste aplikazio-mota batzuetarako ere erabilgarriak dira.
- <textarea>: Lerro anitzeko testua sartzeko eremua.
- rows: Lerro kopurua aldatzeko.
- cols: Zutabe kopurua aldatzeko.
- <input type="color">: Kolore bat hautatzeko hautatzailea.
- value: Lehenetsitako kolorea adieraz daiteke.
- <input type="file">: Gure ordenagailuko fitxategi bat hautatzeko hautatzailea.
- accept: Hautatzaileak erakutsiko duen fitxategi-mota adierazteko aukera ematen du, gainerakoak baztertuz.
- <input type="hidden">: Inprimakiari ezkutuko eremu bat gehitzeko aukera ematen du, erabiltzaileak nahitaez bete behar ez duen beharrezko informazioa bidaltzeko.
Beste kontrol batzuk
<textarea name="textarea" rows="5" cols="30">
Write something here…
</textarea>
<div>
<input type="color" id="foreground" name="foreground" value="#e66465" />
<label for="foreground">Foreground color</label>
</div>
<div>
<label for="avatar">Choose a profile picture:</label>
<input type="file" id="avatar" name="avatar" accept="image/png, image/jpeg" />
</div>
<div>
<input type="hidden" id="postId" name="postId" value="34657" />
</div>
40.2.9 Botoiak
Inprimakiek normalean gutxienez bidalketa-botoi bat izaten dute, baina eremuak berrezartzeko beste botoi bat ere gehi daiteke.
Botoiak
<!-- método antiguo -->
<input type="submit" value="Enviar">
<input type="reset" value="Reset">
<!-- mejor así -->
<button>Aceptar</button>
<button type="reset">Reset</button>
40.3 required atributua duten derrigorrezko kontrolak
Ohikoa da inprimaki baten barruan derrigorrezko kontrolak egotea (izena, pasahitza, emaila…), eta, beraz, erabiltzaileak testua sartu behar izatea.
Zeregin hori errazteko, HTMLek required atributua eskaintzen du. Atributu horrek erabiltzaileari eremua bete behar duela gogorarazten dio. Balidazio hori nabigatzaileak egiten du.
Derrigorrezko kontrolak
<label for="nombre">Nombre</label>
<input id="nombre" type="text" required>
40.4 Etiketak eta irisgarritasuna
Behar bezala programatutako inprimaki bat ez da beti erraza erabiltzeko. Irisgarritasunak eta erabilgarritasunak erabiltzaile orok inprimaki bat eroso bete ahal izatea bilatzen dute, erabilitako gailua edo erabiltzailearen gaitasunak edozein direla ere. Inprimaki irisgarriak diseinatzeak erabiltzaile guztiei egiten die mesede, eta jardunbide egokia da web-garapenean.
Kontrol bakoitzak etiketa deskribatzaile bat izan beharko luke, aurreko adibideetan ikusi dugun bezala. Etiketa horrek, <label>, honako forma hau du:
Etiketa
<label for="nombre">Nombre</label>
<input id="nombre" type="text">
Etiketaren for atributuaren eta kontrolaren id atributuaren arteko erlazioari esker, erabiltzaileak etiketan klik egin dezake kontrola aktibatzeko. Hori bereziki erabilgarria da checkbox eta radio eremuetan.
Erabilgarritasuna hobetzeko, checkbox eta radio kontroletan etiketaren for eta kontrolaren id erabili behar dira.
40.4.1 placeholder atributua
Aurretik ikusi dugu placeholder atributua erabilgarria dela testu-eremuetan, adibideko testu bat erakusteko aukera ematen baitu. Atributu horrek ez du <label> etiketa ordezkatu behar.
40.4.2 Kontrolak taldekatu
Hainbat kontrol talde berekoak direnean, aurretik ikusi dugun <fieldset> etiketa erabiltzea gomendatzen da. Normalean hautaketa-eremuetarako erabiltzen da, baina edozein eremu-motatan erabil daiteke.
41 JavaScript formularioetan erabili
Dagoeneko ikusi dugu HTML bidez inprimakiak nola sortu, baina aplikazio dinamikoak eraikitzeko beharrezkoa da JavaScript-etik kontrolak atzitzea, haien edukia irakurtzeko, aldatzeko edo erabiltzailearen ekintzei erantzuteko.
Atal honetan inprimaki baten gainean egiten diren ohikoenak diren eragiketak ikasiko ditugu.
41.1 Inprimakiaren kontrolak lortu
DOMeko beste edozein elementu bezala, kontrolak ohiko hautaketa-metodoen bidez lor daitezke. Orain arte ikusitako guztia kontuan hartuta, hurrengo adibideetan kontrolen zati bat hautatuko dugu eta haien balioa nola lortu ikusiko dugu.
Kontrolak lortu
// obtener un control concreto
const password = document.querySelector("#password");
console.log(password.value);
// un checkbox o radio
const coding = document.querySelector("#coding");
console.log(coding.checked);
// una lista seleccionable
const lista = document.querySelector("#hr-select");
// valor seleccionado
console.log(lista.value);
// índice del seleccionado
let indice = lista.selectedIndex
console.log(indice);
// texto a través del índice
console.log(lista[indice].text)
// obtener todos los inputs en un array
const controles = document.querySelectorAll("input");
Garrantzitsua da ulertzea value atributuak itzultzen duen guztia testu bat dela; beraz, zenbaki bat espero badugu, bihurtu egin beharko dugu.
Aitzitik, checkbox eta radio lortzeko, checked atributua erabili behar dugu. Atributu horrek balio boolearra itzuliko digu.
Goitibeherako zerrendetan, hautatutako itema eta zerrendan duen kokapena lor daitezke. Zerrenda zerotik hasten da, baina normalean kokapen hori hautatzeko testu estandar baterako erabiltzen da. Kontuan izan behar da, halaber, gauza bat dela erabiltzaileari erakusten zaion option-aren testua eta beste bat value-aren benetako balioa.
Sortu aurretik ikusitako kontrolak dituen inprimaki bat, eta botoia sakatzean balioak lortu. Erabili preventDefault() balioak ikusteko.
41.2 Balioak aldatu
Kontrol baten edukia aldatu eta balio berri bat esleitu nahi badugu, aurreko atalaren antzera egiten da; desberdintasun bakarra da balioa lortu beharrean, esleitu egin behar dugula.
41.3 Formulario osoa lortu
Inprimaki osoa lor dezakegu.
Formulario osoa lortu
const formulario = document.querySelector("#registro");
41.4 Inprimakietan fokua erabili
Fokuak, focus, adierazten du zein kontrol dagoen erabiltzailearen informazioa jasotzeko prest edo une horretan erabiltzen ari den. Elementu batek fokua noiz galdu duen ere jakin dezakegu blur erabiliz.
JavaScript-etik fokua elementu batean koka dezakegu; normalean, oso erabilgarria da balidazio-akats bat detektatzen dugunean. Aurrerago balidazioa nola egin ikusiko dugun arren, erabiltzaileak kontrol bat idazten/erabiltzen duen bakoitzean egin daiteke, edo blur-ekin gertaera bat sor daiteke, kontrolak fokua galtzen duenean balidatzeko.
Gertaera balidatzeko
const password = document.querySelector("#password");
password.addEventListener("blur", (e)=>{
if (password.value.length < 7){
alert("password corta");
}
});
41.5 Kontrolak gaitzea eta desgaitzea
Kontrolak disabled propietatearen bidez gaitu edo desgaitu daitezke; propietate hori boolear motakoa da. HTMLn, atributua gehitzea nahikoa da kontrola desgaituta dagoela adierazteko.
HTML
<input type="text" disabled>
Desgeitu
boton.disabled = true;
Eremua desgaitzen den unean, ezin izango du fokua jaso eta ez da inprimakira bidaliko.
41.6 readonly atributua
readonly propietatea dago kontrol bat aldatu ezin dadin. Erabiltzaileak edukia irakur dezake, kontrolak fokua jaso dezake eta inprimakian bidaliko da. Adibidez, erabiltzaileari aldatu ezin izango duen ID bakarra edo erabiltzaile-izen bat esleitzen zaionean erabiltzen da.
HTML
<input type="text" readonly>
readonly
boton.readonly = true;
42 HTML5 balidazioa
HTML5ek balidazio-sistema integratu bat du, JavaScript koderik idatzi gabe akats asko egiaztatzeko aukera ematen duena. Funtzionalitate horri esker, nahitaezko eremuak, barrutitik kanpoko zenbakiak, posta elektronikoaren helbide okerrak eta beste hainbat egoera detekta daitezke.
Kapitulu honetan zehar atributu horietako batzuk ikusi ditugu dagoeneko, baina hemen berriro zerrendatuko ditugu:
- required: nahitaezko eremua.
- minlength eta maxlength: testuaren tamainarako.
- min eta max: zenbakizko eremuetarako.
- step: zenbakizko eremua egiaztatuko du.
- pattern: adierazitako adierazpen erregularraren bidez egiaztatuko du.
Balidazio horiek guztiak automatikoki egiten dira inprimakia bidaltzeko botoia sakatzean. Balidazio hori nabigatzaileak egiten du, eta datuak zuzenak ez badira, normalean mezu baten bidez adierazten du.
42.1 JavaScript-etik egiaztatzea
JavaScript-ek balidazio horren egoera ere kontsulta dezake checkValidity() funtzioaren bidez. Funtzio horrek balio boolear bat itzultzen du.
HTML
<input type="text" minlength="4">
Egiaztatu balidazioa
nombre.checkValidity();
Balidazioa egoera egiaztatzeaz gain, nabigatzailearen balidazio-mezuak berriro agertzea ere behartu dezakegu.
Balidazioa erakustea
formulario.reportValidity();
Eta agertzen den testua aldatu eta pertsonaliza dezakegu.
Balidazio-testua aldatzea
nombre.setCustomValidity(
"Debe introducir su nombre."
);
42.2 CSS egoerak
HTML5ek kontrol baten egoera adierazten duten pseudo-klaseak ditu. Horrela, gure gustura pertsonaliza dezakegu eta gure aplikazioaren koloreetara egokitu.
Balidaziorako CSSa
input:valid {
border: 2px solid green;
}
input:invalid {
border: 2px solid red;
}
43 JavaScript bidezko balidazioa
Dagoeneko ikusi dugu HTML5ek egiaztapen automatiko ugari dituela, baina badira arau konplexuagoak behar dituzten egoerak, eta horietan JavaScript erabili beharko da. Adibidez:
- Bi pasahitz alderatzea.
- NAN bat balidatzea.
- Data bat beste bat baino beranduagokoa dela egiaztatzea.
43.1 Denbora errealeko balidazioa
Erabiltzaileak testu-eremu batean idazten duen bitartean balidatu dezakegu:
Denbora errealeko balidazioa
nombre.addEventListener("input", () => {
if (nombre.value.length < 3) {
console.log("Nombre demasiado corto.");
}
});
Denbora errealean balidatzen dugunean, akatsak automatikoki detektatzen dira eta erabiltzaileari ohartaraz diezaiokegu gainerako inprimakia betetzen jarraitu aurretik. Horrela, ez ditu aldi berean izan daitezkeen akats guztiak jasoko.
43.2 Inprimakia bidaltzean balidatzea
Erabiltzaileak bidalketa-botoia sakatzean ere egin daitezke egiaztapen guztiak, inprimaki osoa bete ondoren:
Denbora errealeko balidazioa
formulario.addEventListener("submit", (e) => {
if (nombre.value === "") {
e.preventDefault();
alert("Debe introducir un nombre.");
nombre.focus();
}
});
Metodo hau erabiltzeko abantailetako bat da balidazio guztia funtzio berean egon daitekeela. Adibidean ikus daitekeen bezala, balidazioa egin da eta, balidazioa zuzena ez bada, erabiltzaileari abisua ematen zaio eta dagokion eremuan fokua jartzen da.
Balidazioa preventDefault() erabiliz egiten denean, inprimakia bidaltzea saihesten da.
Sortu eremu bat denbora errealean eta eremu guztiak inprimakia bidaltzean balidatzen dituen inprimaki bat.
43.3 HTML5 eta JavaScript konbinatzea
Aplikazio gehienetan bi teknikak erabiltzen dira: HTML5ek akats sinpleenak automatikoki balidatzen ditu, eta JavaScript-ekin aplikazioaren egiaztapen espezifikoak egiten dira. Konbinazio horrek nabarmen murrizten du beharrezkoa den kode-kopurua.
44 Akats-mezuak eta erabiltzaile-esperientzia
Inprimaki bat behar bezala balidatzea ez da soilik erabiltzaileak datu okerrak sartzea eragoztea; garrantzitsua da, halaber, zer akats egin duen eta nola zuzendu dezakeen argi jakinaraztea.
Mezu egokiak erakusten dituen inprimaki bat askoz errazagoa da erabiltzeko datuak bidaltzea besterik gabe eragozten duen beste bat baino. Mezu on batek hiru galdera hauei erantzun beharko lieke:
- Zer gertatu da?
- Zergatik gertatu da akatsa?
- Nola konpon daiteke?
Akats-mezuek argiak, laburrak, zehatzak, adeitsuak eta erabiltzaile teknikoa ez den batek erraz ulertzeko modukoak izan behar dute.
“pattern mismatch” akatsa erabilgarria izan daiteke debugging egiteko, baina ez erabiltzailearentzat.
Aurreko ataletan erabiltzaile-esperientzia ona izateko jarraibide batzuk azaldu baditugu ere, jarraian berriro bilduko ditugu, garapenean jardunbide egokiak izateko.
44.1 Mezuak eremuaren ondoan erakustea
Ahal den guztietan, mezua akatsa duen kontrolaren ondoan agertu behar da. Horrela, erabiltzaileak berehala identifikatuko du zein datu zuzendu behar duen. Horretarako, hasieran ezkutatuta dauden HTML elementuak erabil daitezke, eta, akatsen bat dagoenean, elementu horiek erakutsi:
HTML
<label for="nombre">
Nombre
</label>
<input
id="nombre"
type="text">
<span id="errorNombre"
class="hidden error">
</span>
Balidazio egiaztatu
const nombre = document.querySelector("#nombre");
if (nombre.value === ""){
const er = document.querySelector("#errorNombre");
er.textContent = "Debe introducir un nombre.";
er.mensaje.classList.replace("hidden", "");
}
Balidazioa denbora errealean egiten ari bada, erabiltzaileak akatsa zuzendu ondoren, akats-mezua desagertu egin behar da.
44.1.1 Eremua nabarmentzea
Akats-mezuaz gain, kontrola beste kolore batekin bisualki adieraztea gomendatzen da, akatsa zein eremuk duen nabarmentzeko. Aurretik adierazi dugu HTML5ek CSS klase berezi batzuk dituela, baina gure klase propioak ere sor ditzakegu.
HTML
.error {
border: 2px solid red;
}
JavaScript
// añadir y quitar clase
nombre.classList.add("error");
nombre.classList.remove("error");
Hurrengo irudian erabiltzailearen erregistro-inprimakia ikus daiteke. Bertan, akats-mezu guztiak inprimakiaren hasieran erakustea eta akatsa duten eremuak nabarmentzea aukeratu da.
44.2 Ez ezabatu sartutako informazioa
Inprimakiak akatsak dituenean, erabiltzaileak eremu okerrak soilik zuzendu ahal izatea espero du. Ez luke beharrezkoa izan behar datu guztiak berriro idaztea. Horregatik, normalean ez da inprimakia hustu behar balidazioak huts egiten duenean.
Erabilgarritasunerako garrantzitsua da balidazioa egitean betetako eremuak ez hustea.
44.3 Eremuan fokua jartzea
Aurretik ikusi dugu gomendagarria dela balidatu den eta akatsa duen eremuan kurtsorea jartzea. Horrela, inprimakia handia bada, erabiltzailea berehala has daiteke akatsa zuzentzen.
45 Inprimakiekin ariketak
Unitate honetan zehar HTML inprimakiak sortzen, haien kontrolak JavaScript-etik atzitzen eta erabiltzaileak sartutako informazioa balidatzen ikasi dugu. Atal honetan ezagutza horiek guztiak bilduko ditugu hainbat ariketa garatuz.
Helburua ez da benetako aplikazio bat sortzea, baizik eta adibide bakar batean web-garapenean gehien erabiltzen diren teknikak integratzea.
Sortu eremu hauek dituen inprimaki bat:
- Izena
- Posta elektronikoa
- Adina
- Pasahitza
- Pasahitzaren berrespena
- Erabilera-baldintzen onarpena
Bidali aurretik, honako hauek egiaztatuko dira:
- Nahitaezko eremu guztiak beteta egotea.
- Erabiltzailea adin nagusikoa izatea.
- Bi pasahitzak bat etortzea.
- Erabilera-baldintzak onartu izana.
Erabili HTMLren eta zure balidazioa, eta akatsen bat badago, akatsak erakutsi eta CSSa aldatu.
Sortu ikastetxearen webgunerako inprimaki bat, ikasle berriak erregistratzeko. Honako hauek izan behar ditu:
- Izena
- Abizenak
- Posta elektronikoa
- Adina
- Ikasturtea
- Txanda (goizez edo arratsaldez)
- Iruzkinak
- Pribatutasun-politikaren onarpena
Inprimakiak baldintza hauek bete beharko ditu:
- Eremu guztiak nahitaezkoak izango dira, “Iruzkinak” izan ezik.
- Adinak 16 eta 99 urte artekoa izan beharko du.
- Posta elektronikoak HTML5eko sarrera-mota egokia erabili beharko du.
- Ikasleak pribatutasun-politika onartu beharko du.
- Akatsen bat badago, arazoa adierazten duen mezu bat erakutsiko da eta inprimakia ez da bidaliko.
- Datu guztiak zuzenak badira, erregistroa behar bezala egin dela adierazten duen mezu bat agertuko da.
- Inprimakiak CSS bidezko diseinu sinplea izan beharko du.
Programazio asinkronoa
46 Programazio asinkronoa
Orain arte garatu ditugun programa guztiek ezaugarri komun bat izan dute: instrukzioak bata bestearen atzetik exekutatzen dira. Hala ere, aplikazio askok denbora bat behar izan dezaketen zereginak egin behar dituzte:
- Zerbitzari batetik informazioa deskargatzea.
- Erabiltzaileak botoi bat sakatu arte itxarotea.
- Animazio bat erakustea.
- Ekintza bat segundo batzuk geroago exekutatzea.
- Fitxategi bat irakurtzea.
- Gailuaren GPS kokapena lortzea.
JavaScript-ek eragiketa horietako bakoitza amaitu arte itxaron beharko balu programa exekutatzen jarraitu aurretik, web-orriak blokeatuta geratuko lirateke eta erabiltzaileari erantzuteari utziko liokete.
Arazo hori saihesteko, JavaScript-ek programazio asinkrono eredu bat du. Horri esker, zeregin jakin batzuk abiarazi eta gainerako programa exekutatzen jarrai dezakegu, zeregin horiek amaitu bitartean.
46.1 Eragiketa sinkronoak vs asinkronoak
Eragiketa sinkronoa programa hurrengo instrukzioa exekutatzen hasi aurretik amaitu behar den eragiketa da. Hau da, instrukzioak zorrotz ordenan exekutatzen dira, eta instrukzio bat amaitu arte hurrengoa ez da hasten.
Eragiketa asinkrono batek programa exekutatzen jarraitzea ahalbidetzen du eragiketa hori amaitzen den bitartean. Eragiketa amaitzen denean, JavaScript-ek dagokion kodea exekutatuko du.
| Programazio sinkronoa | Programazio asinkronoa | |
|---|---|---|
| Laburpena | Instrukzioek elkarren zain egon behar dute. | Eragiketa batzuk atzeko planoan exekutatzen dira. |
| Abantailak | ● Ulertzeko erraza da. ● Instrukzioek ordena argi bati jarraitzen diote. ● Erraza da akatsak aurkitzea. |
● Interfazeak erantzuten jarraitzen du. ● Eragiketa geldoetarako egokia da. ● Lineako eskaeretarako egokia da. |
| Desabantailak | Programa blokeatuta gera daiteke. | Fluxu konplexuagoa. |
Imajina dezagun ondorengo JavaScript kodea:
JavaScript
function tarea(message) {
// emula tarea que consume tiempo
let n = 10000000000;
while (n > 0){
n--;
}
console.log(message);
}
console.log('Empieza');
task('Llamamos API');
console.log('Terminado');
- urratsa exekutatzen ari den bitartean, funtzioak denbora behar du eta, beraz, gainerako prozesu guztiak blokeatuta eta zain geratzen dira. Egoera hori saihestu beharreko prozesua da. Web-aplikazio bat erabiltzen dugunean, eragiketa asinkronoak etengabe egiten dira:
- Kanpoko web bateko datuak kontsultatzea.
- Irudiak kargatzea.
- Bideo bat erreproduzitzea.
- Erabiltzailearen klik baten zain egotea.
- Teklatuaren sakatze baten zain egotea.
47 JavaScript eta programazio asinkronoa
JavaScript-ek kodea sekuentzialki exekutatzen du, baina eragiketa asinkronoak kudeatzeko mekanismoak ditu. Mekanismo horiek guztiak lengoaiaren oinarrizko osagai batean oinarritzen dira: Event Loop. Eragiketa horien artean, hauek nabarmendu ditzakegu:
- Tenporizadoreak
- Gertaerak
- Promesak
- async / await
- fetch()
47.1 Event Loop
Event Loop (gertaeren begizta) JavaScript kodearen exekuzioa eragiketa asinkronoekin koordinatzeaz arduratzen den mekanismoa da. Barrutik prozesu konplexua bada ere, modu sinplifikatuan uler dezakegu. Bere lana etengabe galdera honi erantzutea da:
- Ba al dago amaitu den zain dagoen zereginik?
- Erantzuna baiezkoa bada, exekutatu zeregin horri lotutako kodea.
JavaScript single-threaded da, hau da, kode-instrukzio bakarra exekuta dezake aldi berean; beraz, zeregin asinkronoak agertu arte Event Loop ez da jokoan sartzen. Badirudi zeregin gehiago egiten direla, baina horietako batzuk nabigatzaileak egiten ditu. Kodea nola exekutatzen den ulertzeko, “jokalariak” ezagutu behar ditugu:
- Call Stack: Funtzioak exekutatzen diren lekua.
- Web APIs: Nabigatzaileak eskaintzen dituen APIak, zeregin asinkronoak egiteko, hala nola setTimeout, HTTP eskaerak edo DOMeko gertaerak.
- Task Queue (Macro-task queue): Zeregin luzeen callback-ak gordetzen ditu, hala nola setTimeout edo setInterval zereginenak.
- Micro-task Queue: Promise.then-en callback-ak, MutationObserver-en zereginak eta queueMicrotask-en lanak gordetzen ditu.
- Event Loop: Deien pila egiaztatzen duen koordinatzailea: “Deien pila hutsik al dago? Hala bada, joan ilarako hurrengo zereginera.”
JavaScript-ek lehentasun handiagoa ematen die micro-task-ei macro-task-ei baino, eta hurrengo adibidearekin egiazta dezakegu:
medium.com-en adibidea
console.log("1");
setTimeout(() => {
console.log("2 - macro-task");
}, 0);
Promise.resolve().then(() => {
console.log("3 - micro-task");
});
console.log("4");
Nahiz eta oraindik zati bakoitzak zer egiten duen ulertzen ez dugun, irteera honakoa izango da:
- 1
- 4
- 3 - micro-task
- 2 - macro-task
JavaScript-ek lehentasun handiagoa ematen die micro-task-ei macro-task-ei baino.
Bi segundoko tenporizadore bat sortzen duen adibide sinpleagoa
Adibide asinkrono sinplea
console.log("Inicio");
setTimeout(() => {
console.log("Han pasado dos segundos.");
}, 2000);
console.log("Fin");
Programazio asinkronoarekin, garrantzitsua da ulertzea kodearen ordena ez datorrela beti bat exekuzio-ordenarekin.
Egiaztatu aurreko adibideen funtzionamendua.
48 Temporizadoreak
Temporizadoreek kodea denbora jakin bat igaro ondoren edo modu errepikakorrean exekutatzea ahalbidetzen dute. JavaScript-en eskuragarri egon ziren programazio asinkronoko lehen tresnetako batzuk dira.
48.1 setTimeout()
setTimeout() funtzioak funtzio bat behin bakarrik exekutatzen du adierazitako denbora igaro denean, milisegundotan adierazita (1000ms == 1s).
setTimeout() adibidea
console.log("Inicio");
const id = setTimeout(() => {
console.log("Han pasado tres segundos.");
}, 3000);
console.log("Fin");
setTimeout() funtzioak identifikatzaile bat itzultzen du, eta identifikatzaile hori tenporizadorea bertan behera uzteko erabil dezakegu.
48.2 clearTimeout()
Tenporizadore bat exekutatu aurretik bertan behera uzteko aukera ematen du.
setTimeout() adibidea
const id = setTimeout(() => {
console.log("Han pasado cinco segundos.");
}, 5000);
clearTimeout(id);
Funtzio hau erabilgarria da honako hauetarako:
- Atzerako kontaketa bat bertan behera uzteko.
- Jakinarazpen bat gelditzeko.
- Erabiltzaileak iritziz aldatzen badu, ekintza bat exekutatzea saihesteko.
48.3 setInterval()
setInterval() funtzioak funtzio bat behin eta berriz exekutatzen du, adierazitako milisegundoak igaro ondoren.
Funtzio bati deitu
setInterval(hola(), 2000);
Gezi-funtzioa erabili
setInterval(() => {
console.log(new Date());
}, 1000);
Mezua segundo bakoitzean agertzen jarraituko du, harik eta tenporizadorea gelditu arte.
48.4 clearInterval()
setInterval() bidez sortutako tenporizadore bat gelditzeko aukera ematen du.
Tenporizadorea gelditu
let contador = 0;
const reloj = setInterval(() => {
contador++;
console.log(contador);
if (contador === 10) {
clearInterval(reloj);
}
}, 1000);
Egiaztatu tenporizadoreen adibideen funtzionamendua.
48.5 Tenporizadoreekin jardunbide egokiak
Garrantzitsua da jardunbide egokiak erabiltzea tenporizadoreak erabiltzen ditugunean:
- Tenporizadoreek itzultzen duten identifikatzailea gordetzea.
- Jada beharrezkoak ez diren tenporizadoreak bertan behera uztea.
- Tarte laburregiak saihestea, aplikazioaren errendimenduan eragina izan dezaketelako.
49 Callback-ak
Callback bat beste funtzio bati argumentu gisa pasatzen zaion funtzioa da, gero exekutatu dadin. Hau da, funtzio bat berehala exekutatu beharrean, beste funtzio bati ematen zaio, beharrezkoa denean deitu dezan.
Aurreko atalean tenporizadoreak erabiltzen ikasi dugu. Tenporizadoreak set egitean, funtzio bat jasotzen dute lehen parametro gisa. Funtzio hori gertaera jakin bat gertatzen denean exekutatzen da (kasu honetan, denbora jakin bat igarotzen denean).
Callback-ak izan ziren urte askotan JavaScript-en programazio asinkronoa egiteko mekanismo nagusia. Gaur egun ere erabiltzen dira, nahiz eta egoera askotan promesek eta async / await egiturek ordezkatu dituzten. Azken horiek aurrerago aztertuko ditugu.
Callback baten adibidea tenporizadore batean
function saludar() {
console.log("Hola");
}
setTimeout(saludar, 3000);
Kasu honetan:
- saludar callback-a da.
- setTimeout() funtzioak noiz exekutatu erabakiko du.
Aurreko adibidean lehendik existitzen zen funtzio bat pasatu da, baina funtzio anonimoak eta gezi-funtzioak ere pasa daitezke.
Funtzio anonimoa
setTimeout(function () {
console.log("Hola");
}, 3000);
Gezi funtzioa
setTimeout(() => {
console.log("Hola");
}, 3000);
49.1 Noiz erabili callback-ak
Callback hitz ingelesak literalki “itzultzean deitzea” esan nahi du. Beraz, ideia sinplea da: funtzio bati beste funtzio bat ematea, beharrezkoa denean deituko dena.
Adibide gisa, har dezagun eragiketa bat egiten duen hurrengo funtzioa. Hirugarren parametro gisa callback funtzio bat du, emaitzarekin zer egin behar den adierazteko. Funtzioak ez daki zer gertatuko den emaitzarekin, baina callback-a erabiliko du horretarako.
Callback adibidea
function sumar(a, b, callback) {
const resultado = a + b;
callback(resultado);
}
Funtzioari deitzean, parametro gisa pasatzen diogun callback-ean zer egin erabaki dezakegu.
Emaitza logueatu
sumar(4, 6, (resultado) => {
console.log(resultado);
});
Elementu batean jarri
sumar(4, 6, (resultado) => {
let r = document.getElementById("r")
r.textContent = resultado
});
Lehen deian emaitza kontsolan logeatzen da; bigarrenean, berriz, HTML elementu bat aldatzen da.
Sortu parametro gisa callback bat jasotzen duen funtzio bat. Deitu funtzioari callback desberdin batekin.
49.2 Callback-ak gertaeretan
Dagoeneko callback-ak erabiltzen aritu gara, konturatu gabe.
Callback gertaeretan
boton.addEventListener("click", () => {
console.log("Pulsado");
});
Aurreko gezi-funtzioa callback bat da, eta nabigatzaileak exekutatuko du erabiltzaileak botoia sakatzen duenean.
Orain arte ikusi ditugun gertaera guztiek callback-ak erabiltzen dituzte, eta gauza bera gertatzen da tenporizadoreekin.
Gertaera eta tenporizadore guztiek callback-ak dituzte.
49.3 Callback hell
Aplikazio bat hazten hasten denean, callback-ek kodea zaildu dezakete. Hainbat callback elkarren barruan habiaratzen direnean, Callback Hell izenez ezagutzen den arazo bat agertzen da. Pyramid of Doom edo Zoritxarraren Piramide ere esaten zaio.
Izena kodearen itxuratik dator, koska-mailak direla eta piramide bat gogorarazten baitu. Ikusmenez, kodea jarraitzea zaila da, eta, gainera, edozein aldaketak piramidearen hainbat mailatan eragin dezake.
Callback hell
login(usuario, () => {
obtenerPerfil(() => {
obtenerPedidos(() => {
obtenerFactura(() => {
console.log("Proceso terminado");
});
});
});
});
Callback-en bidezko erroreen kudeaketa ere ez da erraza. Eragiketa bakoitzak egiaztatu beharko luke arazoren bat gertatu den jarraitu aurretik. Horrek are gehiago handitzen du kodearen konplexutasuna.
49.4 Abantailak eta desabantailak
Callback-ek aurrerapen handia ekarri zuten JavaScript-era, programaren exekuzioa blokeatu gabe ataza asinkronoak egitea ahalbidetzen baitzuten. Hala ere, desabantaila batzuk ere badituzte, hurrengo taulan ikus daitekeen bezala.
| Abantailak | Desabantailak |
|---|---|
| ● Gertaera bat gertatzen denean kodea exekutatzea ahalbidetzen dute. ● Aplikazioa blokeatzea saihesten dute. ● Eragiketa txikietarako sinpleak dira. ● Nabigatzailearen ia API guztietan daude eskuragarri. ● JavaScript-eko metodo ugaritan erabiltzen jarraitzen dira. |
● Kodea mantentzea zaila izan daiteke. ● Habiaratutako funtzio asko. ● Erroreen kudeaketa konplikatua. ● Irakurgarritasun txikia. ● Kodea berrerabiltzea zaila. |
50 Promesak (Promise)
Aurreko atalean ikusi dugu callback-ek kodea eragiketa asinkrono bat amaitzen denean exekutatzea ahalbidetzen dutela. Hala ere, hainbat eragiketa elkarren mende daudenean, kodea irakurtzea eta mantentzea zaila izan daiteke.
Arazo hori konpontzeko, ECMAScript 2015ek (ES6) Promise (promesa) izeneko mekanismo berri bat gehitu zuen. Mekanismo horrek eragiketa asinkrono baten emaitza irudikatzea ahalbidetzen du eta hainbat eragiketa kateatzea errazten du, Callback Hell ezaguna sortu gabe. Gaur egun, JavaScript-eko programazio asinkronoaren oinarrizko mekanismoetako bat da.
Promesa bat sortzen dugunean, oraindik ez dugu eragiketa horren emaitza ezagutzen. Dakigun bakarra da noizbait bi egoera hauetako bat gertatuko dela:
- Eragiketa behar bezala amaituko da.
- Eragiketak errore bat sortuko du.
50.1 Promise baten egoerak
Promesa bakoitzak hainbat egoera igarotzen ditu, eta ondorengo diagraman modu sinplifikatuan ikus daitezke:
- Pending: Hasierako egoera da. Eragiketa oraindik ez da amaitu.
- Fulfilled: Eragiketa behar bezala amaitu da. Promesak emaitza bat itzultzen du.
- Rejected: Eragiketak errore bat sortu du. Promesak hutsegitearen arrazoia itzultzen du.
50.2 Promise bat sortzea
Promise bat sortzeko modua hurrengo adibideetan agertzen dena da. Funtzioak bi parametro berezi jasotzen ditu, promesa ebatzi edo bazter dezaketen bi funtzio (callback):
- resolve(): Eragiketa behar bezala amaitu dela adierazten du. Promesa fulfilled egoerara igarotzen da.
- reject(): Eragiketak errore bat sortu duela adierazten du. Promesa rejected egoerara igarotzen da.
Jarraian, bi adibide sortzen dira:
- Promesa ebatzi edo baztertzen duen baldintza batekin egindako adibide sinplea.
- Bi segundoren buruan promesa ebatzi edo baztertuko duen adibidea, tenporizadoreari esker. Horrela, eskaera asinkrono bat simulatzen da (web bateko eskaera bat, adibidez).
Promise sortu
const p=new Promise((resolve,reject)=>{
// Tareas asíncronas
// cambiar a false para ver error
const success = true;
if (success) {
resolve("éxito");
} else {
reject("error");
}
});
Promise sortu
const p=new Promise((resolve,reject)=>{
// Tareas asíncronas
// cambiar a false para ver error
const success = true;
setTimeout(() => {
if (success) {
resolve("éxito")
} else {
reject("error")
}
}, 2000)
});
50.3 Promise kontsumitzea
Promise bat sortu ondoren, kontsumitu egin behar da modu asinkronoan egindako funtzioaren balioa lortu ahal izateko. Horretarako, metodo hauek ditugu:
- then(): Promise arrakastaz ebazten denean exekutatzen da.
- catch(): Promise errore batekin baztertzen denean exekutatzen da.
- finally(): Beti exekutatzen da, promesaren prozesua amaitzean (then() edo catch() ondoren). Ez du parametrorik jasotzen eta ezin du promise-aren balioa aldatu. Funtzio hau erabilgarria da honako hauetarako:
- Kargatze-adierazleak ezkutatzeko.
- Baliabideak askatzeko.
- Interfazea leheneratzeko.
Consumir Promise
promesa
.then((respuesta)=>{
console.log(`Éxito: ${respuesta}`)
})
.catch((error)=> {
console.log(`Error: ${error}`)
})
.finally(()=>{
console.log("Promesa finalizada.")
});
then() eta catch elkarren baztertzaileak dira. Horietako bakarra exekutatzen da.
Sortu egoera desberdinetan amaitzen diren Promesak. Erabili finally() azken funtzio gisa.
50.4 Eragiketak kateatu
Hainbat then() metodo modu kateatuan erabiltzea posible da. Izan ere, then() batek Promise berri bat itzultzen du, eta horri esker emaitzen eraldaketa-kate bat sor daiteke; izan ere, bakoitzak bere emaitza hurrengoari pasa diezaioke:
Eragiketak kateatu
promesa
.then((respuesta)=>{
console.log(`Éxito 1: ${respuesta}`)
return respuesta;
})
.then((respuesta)=> {
r = respuesta.toUpperCase();
console.log(`Éxito 2: ${r}`);
return r;
})
.then((respuesta)=> {
r = respuesta.toLowerCase();
console.log(`Éxito 3: ${r}`);
});
Aurreko adibidean ikus daitekeen bezala, eragiketa hauek egiten dira:
- Lehen then()-ean promesaren erantzuna jasotzen dugu; kasu honetan, kontsolan logeatzen dugu eta erantzunaren return egiten dugu.
- Testu/objektu hori hurrengo then()-ean jasotzen da parametro gisa. Honek, aldi berean, zenbait eragiketa egiten ditu eta beste testu/objektu bat itzultzen du.
- Azken then()-ean aurrekoaren return jasotzen dugu parametro gisa, eta hirugarren eragiketa bat egiten dugu.
Hori guztia sinplifikatu egin daiteke aurretik idatzitako funtzioei dei egiten badiegu.
Eragiketak kateatu
promesa2
.then(respuesta => igual(respuesta))
.then(respuesta => mayus(respuesta))
.then(respuesta => minus(respuesta));
Eta are gehiago hobetu dezakegu, une bakoitzean exekutatu nahi ditugun funtzioak zuzenean pasa baititzakegu. Funtzio horiek aurreko urratsaren emaitza jasoko dute, funtzioak habiaratu beharrik gabe. Hori gertatzen da funtzioaren kontratuak parametro bakarra jaso eta promesa bat itzultzea eskatzen duelako, sortzen ari garen funtzioak bezala:
Eragiketak kateatu
promesa3
.then(igual)
.then(mayus)
.then(minus);
Sortu eragiketa kateatuak dituzten promesak eta erabili eragiketak idazteko hiru moduak.
50.5 Callback-ekiko abantailak
Jarraian, eragiketa berak callback-ekin eta Promise-ekin nola egin daitezkeen erakusten duen adibide bat:
123 erabiltzailearen saio-hasierako Callback hell-a
login(123, (error,usuario) => {
if (error) {
console.log("Error de login");
} else {
obtenerPerfil(usuario.id,(error,perfil) => {
if (error){
console.log("Error de perfil");
} else {
obtenerPedidos(usuario.id, (error, pedidos) => {
if (error){
console.log("Error en pedidos");
} else {
obtenerFactura(pedidos[0].id,(error,factura) => {
if (error){
console.log("Error en factura")
} else {
// obtener total, productos...
}
});
}
});
}
});
}
});
Callback hell adibide honetan erroreen kudeaketa eta egiaztapenak gehitu dira, aurreko atalean adierazi ez zirenak. Ikus daitekeen bezala, horrek etorkizunean aldaketak egin behar direnean zailtasuna handitzen du.
Aldiz, Promise erabiltzen badugu, hurrengo bi moduetako bat izango genuke, bertsio “luzea” edo laburtua erabiltzen dugunaren arabera.
Erabiltzailearen saio-hasiera
obtenerUsuario(123)
.then((usuario) => {
return obtenerPerfil(usuario.id);
})
.then((usuario) => {
return obtenerPedidos(usuario.id);
})
.then((pedidos) => {
return obtenerFactura(pedidos[0].id);
})
.then((factura) => {
console.log(factura);
})
.catch((error) => {
console.error(error);
});
Erabiltzailearen saio-hasiera
obtenerUsuario(123)
.then(obtenerPerfil)
.then(obtenerPedidos)
.then(obtenerFactura)
.then(mostrarFactura)
.catch((error) => {
console.error(error);
});
50.6 Promise.all()
Hainbat promesa amaitu arte itxarotea ahalbidetzen du, ondoren funtzio bat exekutatzeko. Hala ere, funtzioa promesa guztiak behar bezala amaitu direnean bakarrik exekutatuko da:
Promesak itxaroten
Promise.all([
promesa1,
promesa2,
promesa3
])
.then((resultados) => {
console.log(resultados);
});
Promesetako edozeinek errore bat sortzen badu, Promise.all() berehala amaituko da errore horrekin.
50.7 Promise.race()
Amaitzen den lehen promesaren emaitza itzultzen du, edozein dela ere zein promesa den.
Promesak itxaroten
Promise.race([
promesa1,
promesa2
])
.then((resultado) => {
console.log(resultado);
});
50.8 Promise.allSettled()
Hainbat Promise-ren emaitza itxaroteko erabiltzen da, horietako batzuek huts egiten duten kontuan hartu gabe. Erabilgarria da egoera-txosten bat egiteko, zer funtzionatu duen eta zer ez jakiteko.
Promise.allSettled() erabiliz, beti {status, value/reason} motako objektuen array bat lortuko dugu.
- status: fulfilled balioa izan dezake promesak bete badira, eta rejected baztertu badira.
- Bigarren eremua hau izango da:
- value: promesak arrakasta izan badu, emaitza izango dugu.
- reason: promesak huts egin badu, errorea izango dugu.
Sortu adibideak Promise.all(), Promise.race() eta Promise.allSettled() erabiliz.
51 async eta await
Promesek callback-en arazoen zati handi bat konpondu zuten. Hala ere, hainbat promesa kateatzen direnean, kodea nahi baino konplexuagoa izan daiteke.
Programazio asinkronoa are gehiago sinplifikatzeko, ECMAScript 2017k async eta await hitz erreserbatuak gehitu zituen. Haien helburua kode asinkronoa kode sekuentzialaren oso antzeko itxurarekin idaztea da.
async eta await hitzen helburua kode asinkronoa kode sekuentzialaren antzeko itxurarekin idaztea da.
51.1 async funtzioa deklaratzea
async hitz erreserbatua erabiliz, funtzio bat asinkronoa dela deklaratzen dugu eta beti promesa bat itzultzen du. Funtzio estandarretan zein gezi-funtzioetan erabil dezakegu.
async funtzioa
async function saludo() {
return "Hola";
}
gezi funtzioa async
const saludo = async () => {
return "Hola";
};
Itxuraz kate bat itzultzen badu ere, benetan balio horrekin ebatzitako promesa bat itzultzen du.
51.2 await bidez funtzioa itxarotea
await hitz erreserbatuak promesa baten emaitza itxaroteko aukera ematen du. Promesa amaitzen ez den bitartean, funtzio asinkronoa zain geratuko da. Gogoratu behar dugu horrek ez duela programa osoa blokeatzen; JavaScript-ek funtzio hori alde batera utziko du eta programaren beste zati bati ekingo dio.
Funtzioa Promise itzultzen du
function esperar() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("Finalizado");
}, 2000);
});
}
Funtzio asinkronoa itzaroten du
async function ejemplo() {
console.log("Inicio");
const resultado = await esperar();
console.log(resultado);
console.log("Fin");
}
ejemplo();
Aurreko adibidean badirudi modu sinkronoan exekutatzen ari dela, baina aplikazioaren gainerakoa blokeatzea saihestea ahalbidetzen duten JavaScript-en funtzioak erabili dira.
Sortu 3 botoi, honako hau egiten dutenak:
"Botón 1 pulsado"logeatu.- Deitu 18a ariketako task funtzioari. Saiatu 1. botoia sakatzen. Zer gertatzen da?
- Deitu aurreko adibideko async funtzio baten antzeko bati eta itxaron await erabiliz. Saiatu 1. botoia sakatzen. Zer gertatzen da?
Jarraian, promesak erabiliz egindako adibide baten eta async/await erabiliz egindako beste baten arteko konparaketa ikus dezakegu.
Promesekin
esperar()
.then((resultado) => {
console.log(resultado);
});
Async/await
const resultado = await esperar();
console.log(resultado);
51.3 Erroreen kudeaketa
Promesa batek errore bat sortzen duenean, normalean try…catch erabiliko dugu.
Errore kudeaketa
async function ejemplo() {
try {
const datos = await obtenerDatos();
console.log(datos);
}
catch(error){
console.log(error);
}
}
Nahiz eta try…catch lehenago aztertu genuen, une honetatik aurrera bereziki garrantzitsua izango da, funtzio asinkronoetako erroreak kudeatzeko ohiko mekanismoa baita.
51.4 Hainbat eragiketa
Promise-ekin eragiketak nola kateatu ikusi dugu. Orain hainbat funtziori dei egin diezaiekegu eta emaitzaren zain egon, modu irakurgarriagoan:
Promesekin
obtenerDatos()
.then((datos) => {
return procesar(datos);
})
.then((resultado) => {
console.log(resultado);
})
.catch((error) => {
console.log(error);
});
Async/await
async function ejemplo() {
try {
const datos = await obtenerDatos();
const resultado = await procesar(datos);
console.log(resultado);
}
catch(error){
console.log(error);
}
}
Horren arazoa da modu sekuentzialean programatzen ari garela; beraz, bi funtzioen denborak batzen ari gara. Horregatik, garrantzitsua da gogoratzea paraleloan itxaron dezakegula Promise.all erabiliz.
Itxaron paraleloki
async function perfilUsuario(id) {
try {
const [datos, facturas] = await Promise.all([
obtenerDatos(id),
obtenerFacturas(id)
])
console.log(facturas);
}
catch(error){
console.log(error);
}
}
Sortu 3 botoi, funtzio desberdinei deitzen dietenak. Funtzio horiek, aldi berean, 3, 2 eta 1 segundoko tenporizadore bana erabiliko dute. Zein moduk behar du denbora gutxien exekutatzeko?
- Promise erabiliz, then habiaratuz.
- async/await erabiliz, modu sekuentzialean.
- async/await erabiliz, Promise.all paraleloan erabiliz.
51.5 Noiz erabili async eta await?
Promesekin lan egiten dugunean eta hainbat eragiketa jarraian egin behar ditugunean. Gaur egun, JavaScript aplikazio modernoak garatzeko gomendatutako ikuspegia dira.
Komunikazioa zerbitzariekin
52 Fetch API
Fetch API nabigatzaileak eskaintzen duen interfaze bat da, HTTP eskaerak modu asinkronoan egiteko aukera ematen duena. Bere funtzio nagusia web-zerbitzariekin komunikatzea da, honako hauek egiteko:
- Informazioa deskargatzeko.
- Inprimakiak bidaltzeko.
- REST API bat kontsultatzeko.
- Fitxategiak igotzeko.
- Zerbitzari bateko informazioa ezabatzeko.
fetch() funtzioak Promise bat itzultzen du. Beraz, aurreko kapituluan ikusitako guztia erabili ahal izango dugu: .then, .catch, async eta/edo await.
52.1 JavaScript-eko komunikazio asinkronoen bilakaera
JavaScript-en lehen urteetan ez zegoen nabigatzailetik HTTP eskaerak egiteko modu errazik, orri osoa berriro kargatu gabe. Horretarako, XMLHttpRequest (XHR) agertu zen, Microsoft-ek 1999an Internet Explorer 5.0-n aurkeztutako APIa (ActiveX erabiliz). Ondoren, Mozilla 2002an eta Safari 2004an batu ziren. 2006an, W3C erakundeak estandar bat sortzeko lehen zirriborroa aurkeztu zuen.
Teknologia horretatik AJAX (Asynchronous JavaScript and XML) terminoa sortu zen. Garrantzitsua da azpimarratzea AJAX ez dela liburutegi bat, ezta funtzio bat ere, baizik eta garapen-teknika bat. Teknika horrek JavaScript eta XMLHttpRequest erabiltzen ditu zerbitzariarekin informazioa trukatzeko, orria berriro kargatu gabe.
Garai hartan, XML erabiltzea zen “makinen arteko” komunikaziorako (sare bidez) de facto formatu estandarra; hortik dator bere izenean XML aipatzea. Denborarekin, JSON formatuak XML ordezkatu zuen ia erabat, sinpleagoa delako.
AJAXen ospe handieneko garaian, nabigatzaileen arteko bateragarritasuna izan zen garatzaileentzako arazo nagusietako bat. Guztiek XMLHttpRequest APIa eskaintzen bazuten ere, desberdintasunak zeuden haren inplementazioan eta portaeran, bereziki Internet Explorer, Firefox, Opera eta WebKit-en oinarritutako lehen nabigatzaileen artean.
jQuery-k zeregin hori asko sinplifikatu zuen, AJAX eskaerak egiteko interfaze bakarra eskaintzen baitzuen, hala nola $.ajax(), $.get() edo $.post() funtzioen bidez. Horrela, kode berak oso antzeko moduan funtzionatzen zuen nabigatzaile desberdinetan, eta garatzaileak ez zuen horietako bakoitzerako soluzio espezifikorik programatu behar.
ECMAScript modernoaren etorrerarekin Fetch API agertu zen. HTTP eskaerak egiteko modu askoz errazagoa eta irakurgarriagoa eskaintzen du, eta nabigatzaile guztiek betetzen duten estandarra da.
| Teknologia | Zer da? | Egungo egoera |
|---|---|---|
| XMLHttpRequest (XHR) | HTTP eskaerak egiteko nabigatzailearen APIa. | Oraindik bateragarria da, baina gero eta gutxiago erabiltzen da. |
| AJAX | Hasiera batean XMLHttpRequest-en oinarritutako garapen-teknika. |
Kontzeptuak indarrean jarraitzen du, nahiz eta normalean fetch() erabiliz inplementatzen den. |
| Fetch API | Promesetan oinarritutako HTTP eskaerak egiteko API modernoa. | Egungo web-garapenean gomendatutako aukera da. |
52.2 Eskaera sinple bat egin
Modurik errazena baliabidearen/zerbitzariaren helbidea bakarrik adieraztea da eta, esan bezala, Promise bat itzultzen duenez, kasu honetan then erabiliko dugu erantzuna lortzeko.
Fetch eskaera egin
fetch("https://jsonplaceholder.typicode.com/users")
.then((respuesta) => {
console.log(respuesta);
});
Aldagaia respuesta zerbitzariari egindako HTTP erantzunari buruzko informazioa dauka, ez ditu behar ditugun datuak.
fetch egitean, lehenik HTTP erantzuna lortzen dugu; ez ditu bilatzen ari garen datuak.
52.2.1 Response objektua
fetch()-ek itzultzen duen erantzuna Response motako objektu bat da. Objektu horrek honako informazioa dauka, besteak beste:
- status: HTTP eskaeraren erantzun-kodea.
- 200: eskaera zuzena.
- 201: baliabidea sortu da.
- 301: behin betiko lekuz aldatu da.
- 401: baimenik gabe.
- 404: baliabidea ez da aurkitu.
- 418: teontzi bat naiz.
- 500: barne-zerbitzariaren errorea.
- ok: boolear bat itzultzen du eskaera zuzena izan den jakiteko (200 eta 299 artean).
- headers: HTTP goiburuak.
- Eduki-mota.
- Erantzunaren gorputza.
Response objektua
fetch("https://jsonplaceholder.typicode.com/users")
.then((respuesta) => {
console.log(respuesta.status);
console.log(respuesta.ok);
if (!respuesta.ok) {
throw new Error("Error en la petición.");
}
});
52.2.2 Edukia lortu
Zerbitzariari eskatu dizkiogun datuak lortzeko, lehenik erantzuna formatu egoki batera bihurtu behar dugu. Ondorengo metodoen artean aukera dezakegu:
- json(): datuak JSON formatura bihurtzen ditu. APIekin komunikatzeko metodoa.
- text(): testu arrunt gisa lortzen du.
- blob(): fitxategi bitarretarako (irudiak, bideoak, fitxategiak).
- arrayBuffer(): bitar gordinetarako, fitxategien manipulazio aurreraturako.
- formData(): inprimakietarako.
JSON formatua aukeratuko dugu; horrela, datuak modu errazagoan atzitu ahal izango ditugu, JavaScript-ekin erraz kudeatzeko moduko objektu bihurtuko baitira.
json()-i egindako deiak ere promesa bat itzultzen du. Horregatik, bigarren then() bat edo bigarren await bat beharko dugu, aukeratutako moduaren arabera.
json()-i egindako deiak ere promesa bat itzultzen du.
Promise-ekin
fetch(URL)
.then((respuesta) => {
return respuesta.json();
})
.then((datos)=>{
console.log(datos)
})
.catch((error)=> {
console.log(error);
});
Async / await
async function cargarUsuarios() {
const respuesta = await fetch(URL);
const usuarios = await respuesta.json();
console.log(usuarios);
}
cargarUsuarios();
52.3 Erroreen kudeaketa
Eskaerak egitean erroreak kudeatzeko, try…catch erabiliko dugu.
Eskaeren erroreak kudeaketa
const URL = "https://jsonplaceholder.typicode.com/users";
async function cargarDatos() {
try {
const respuesta = await fetch(URL);
const datos = await respuesta.json();
console.log(datos);
}
catch(error){
console.error(error);
}
}
Sortu 2 botoi, eta bakoitzak API batera deitu behar du promesak eta async/await erabiliz, datuak hurrenez hurren lortzeko.
53 REST APIekiko komunikazioa
Fetch-en aplikazio garrantzitsuenetako bat REST APIekin komunikatzea da. Gaur egun, web-, mugikor- eta mahaigaineko aplikazio gehienek zerbitzu mota hauek erabiltzen dituzte informazioa trukatzeko.
API (Application Programming Interface) bi programaren arteko komunikazioa ahalbidetzen duen arau-multzoa da. API batek honako hauek definitzen ditu:
- Zer eragiketa egin daitezkeen.
- Nola bidali behar diren datuak.
- Zer erantzun itzuliko dituen zerbitzariak.
53.1 API baliabideak
API batek informazioa baliabideetan antolatu ohi du, eta baliabide horietako bakoitzak URL espezifiko bat du. Datu fake dituen {JSON} Placeholder API publikoa adibide gisa hartuta, baliabideak hauek izango lirateke:
- /users: erabiltzaile guztiak lortzea.
- /users/1: 1 IDa duen erabiltzailea lortzea.
- /posts: post guztiak lortzea.
- /posts/1/comments: 1 IDa duen post-aren iruzkinak lortzea.
- /comments: iruzkin guztiak lortzea.
Normalean, API publikoek web-interfaze bat izaten dute, kontsumitu ditzakegun datu-ereduak eta metodoak/baliabideak erakusteko. Ohikoa da OpenAPI zehaztapena erabiltzea. Adibidez:
- Swagger: web-interfazea. Adibide bat OpenData Euskadi atarian ikus dezakegu.
- Scalar: web-interfaze modernoagoa.
53.2 Zer esan nahi du RESTek?
REST (Representational State Transfer) web-zerbitzuak sortzeko diseinu-estilo bat da. REST API batean baliabide bakoitzak helbide bat (URL) du, eta HTTP metodoen bidez manipulatzen da.
API batekin komunikatzeko erabiltzen diren HTTP metodoak hauek dira, nahiz eta beste batzuk ere badauden:
| Metodoa | URLa | Ekintza |
|---|---|---|
| GET | /users | Erabiltzaile guztiak itzultzen ditu. |
| GET | /users/15 | 15 IDa duen erabiltzailea itzultzen du. |
| POST | /users | Erabiltzaile berri bat sortzen du. |
| PUT | /users/15 | Lehendik dagoen baliabide bat ordezkatzen du. |
| PATCH | /users/15 | Baliabide bat partzialki aldatzen du. |
| DELETE | /users/15 | Erabiltzaile hori ezabatzen du. |
2026ko ekainera arte, QUERY metodo berri bat proposatu da, RFC 10008 dokumentuan zehaztuta. Bideo honetan, midudev-ek etorkizunean nola funtzionatuko duen azaltzen du.
54 REST API oso bat kontsumitzea
Orain arte, fetch() bidez HTTP eskaerak egiten eta erantzunak promesak eta async / await erabiliz prozesatzen ikasi dugu. Orain, aurretik ikusitako kontzeptuak biltzen dituen adibide oso bat garatuko dugu. Horretarako, {JSON} Placeholder API publikoa erabiliko dugu, eta honako hauek egiteko gai izango den aplikazio txiki bat eraikiko dugu:
- Zerbitzaritik informazioa lortzea.
- Datuak HTML taula batean erakustea.
- Erregistro berriak sortzea.
- Lehendik dauden erregistroak aldatzea.
- Erregistroak ezabatzea.
54.1 Datuak GET bidez lortzea
Erabiltzaileen zerrenda deskargatuko dugu. Horretarako, aurretik ikusi dugun bezala, fetch() eskaera bat egingo dugu:
Erabiltzaileak lortu
async function cargarUsuarios() {
try {
const respuesta = await fetch(
"https://jsonplaceholder.typicode.com/users"
);
if (!respuesta.ok) {
throw new Error("Error al obtener los usuarios.");
}
const usuarios = await respuesta.json();
console.log(usuarios);
}
catch (error) {
console.error(error);
}
}
54.2 Datuen erakusketa
Erabiltzaileak lortu ondoren, array-a zeharkatu eta HTML taula batean txerta ditzakegu.
HTML taula
<table>
<thead>
<tr>
<th>Id</th>
<th>Nombre</th>
<th>Email</th>
</tr>
</thead>
<tbody id="usuarios">
</tbody>
</table>
Txertatu data taulan
for (const usuario of usuarios) {
const fila = document.createElement("tr");
// TODO: cambiar innerHTML por createElement
fila.innerHTML = `
<td>${usuario.id}</td>
<td>${usuario.name}</td>
<td>${usuario.email}</td>
`;
tbody.appendChild(fila);
}
54.3 Erregistro berri bat sortzea POST bidez
Erabiltzaile berri bat sortzeko, POST metodoa erabili behar dugu. Datuak inprimaki baten bidez lor ditzakegu (behar bezala balidatuta).
Erregistro berria sortu POST-ekin
const usuario = {
name: "Alice",
email: "alice@example.com"
};
const respuesta = await fetch(
"https://jsonplaceholder.typicode.com/users",
{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(usuario)
}
);
Jarraian, fetch() metodo honen arteko aldea azaltzen da, aurretik ikusitakoaren zertxobait desberdina baita. Orain, bigarren parametro bat jasotzen du, aukerekin:
- URLa: orain arte ikusi dugun bezala, eskaera egingo dugun URLa adierazi behar dugu.
- options: hainbat aukera dituen objektua:
- method: eskaera egitean erabiliko den metodoa; kasu honetan, POST.
- headers: eskaera egitean bidal daitezkeen HTTP goiburuak.
- Content-Type: bidaliko den eduki mota. Normalean, APIak erabiltzean JSON erabiltzen da.
- body: eskaerarekin batera bidaltzen den edukia; kasu honetan, erabiltzaile berri baten datuak.
JavaScript-eko objektuak ezin dira zuzenean HTTP bidez bidali; lehenik, JSON kate bihurtu behar dira. Horretarako, JSON.stringify() funtzioa dago, objektua JSON formatura bihurtzen duena.
54.4 Erregistro bat aldatzea (PUT / PATCH)
Informazio-erregistro bat aldatzeko orduan, bi metodo erabil ditzakegu:
- PUT: baliabidea erabat ordezkatzen du.
- PATCH: eremu batzuk soilik aldatzea ahalbidetzen du.
PUT metodoa
await fetch(
"https://URL/users/3",
{
method: "PUT",
headers: {
"Content-Type":"application/json"
},
body: JSON.stringify({
id:3,
name:"María",
email:"maria@example.com",
// resto de campos
})
}
);
PATCH metodoa
await fetch(
"https://URL/users/3",
{
method: "PATCH",
headers: {
"Content-Type":"application/json"
},
body: JSON.stringify({
email:"nuevo@email.com"
})
}
);
{JSON} Placeholder zerbitzuak ez du aldaketarik egitea ezta datuak ezabatzea ere ahalbidetzen, baina eskaerei behar bezala erantzungo die.
54.5 Erregistro bat ezabatzea DELETE bidez
Baliabide bat ezabatzeko, DELETE HTTP metodoa erabiltzen dugu. Eragiketa behar bezala amaitzen bada, baliabidea ezabatuta egongo da.
DELETE metodoa
await fetch(
"https://jsonplaceholder.typicode.com/users/3",
{
method:"DELETE"
}
);
Azken adibideetan ez dugu try…catch erabili, ezta eskaeraren egoera egiaztatu ere, adibideak sinplifikatzeko. Baina erabili egin behar dira.
Sortu orri bat, beharrezkoa denean honako fetch eskaerak egiten dituena:
- Erabiltzaileak lortu eta taula batean txertatu.
- Errenkada bakoitzak “Ekintzak” izeneko zutabe bat izango du, eta bi botoi izango ditu:
- “Editatu”: erabiltzailearen datuak editatzeko (inprimaki bat duen leiho modala irekiko du).
- “Ezabatu”: erabiltzaile zehatza ezabatzeko. Errenkada ezabatuko du.
- “Erabiltzailea gehitu” botoiak inprimaki bat duen leiho modala irekiko du, erabiltzaile bat sortzeko.
- Eremuak balidatuta egongo dira.
- Nabigatzailearen mezuak aldatuko dira.
- Taularen amaieran gehituko da.
- Errenkada bakoitzak “Ekintzak” izeneko zutabe bat izango du, eta bi botoi izango ditu:
55 REST APIetarako garapen-tresnak
Orain arte, fetch() erabiliz HTTP eskaerak egiten ikasi dugu. Hala ere, aplikazio batek behar bezala funtzionatzen ez duenean, ezinbestekoa da nabigatzailearen eta zerbitzariaren artean zer gertatzen ari den jakitea.
55.2 APIak probatzeko tresnak
Aplikazio baten garapenean, probak nabigatzailetik edo garatzen ari garen aplikaziotik bertatik egitea ez da beti praktikoa. Askotan komenigarria da HTTP eskaerak zuzenean API batera bidaltzea eta lortutako erantzunak aztertzea ahalbidetzen duten tresnak erabiltzea.
Aplikazio horiek eskaerak bidaltzea errazten dute, HTTP goiburuak, parametroak eta autentifikazioa gehitzeko aukera ematen dute, eta zerbitzariaren erantzunak modu argian ikusteko aukera ere bai. Gainera, eskaerak proiektuen/endpoint-en araberako bildumetan gorde daitezke.
Dauden aplikazioen artean, honako hauek nabarmendu ditzakegu: Postman, Firecamp (web edo mahaigaineko bertsioa), Bruno edo Insomnia.

Linux kontsola batetik, curl komandoa erabiliz, endpoint-a funtzionatzen ari den ere azkar egiazta dezakegu:
curl-en erabilera kontsolan
ruben@vega:~$ curl -s http://localhost/api/posts
{"posts":[{"id":1,"titulo":"Primer post111","texto":"Este es...”}]}
Emaitza ikusgarriagoa lortu nahi badugu, jq komandoa erabil dezakegu, eta horretarako instalatu egin beharko dugu. Horrela, honako hau egin ahal izango dugu:
“jq” komandoa emaitza formateatzeko
ruben@vega:~$ curl -s http://localhost/api/posts | jq
{
"posts": [
{
"id": 1,
"titulo": "Primer post",
"texto": "Este es el texto del primer post",
"publicado": 1,
"deleted_at": null,
"created_at": "2024-10-29T17:09:56.000000Z",
"updated_at": "2024-10-29T18:09:56.000000Z"
}
]
}
Tresna hauek APIak garatzeko eta arazteko oso erabilgarriak diren arren, komeni da gogoratzea ez dutela fetch() ordezkatzen. Haien helburua web-zerbitzu batek behar bezala funtzionatzen duela egiaztatzea da, gure JavaScript aplikazioan integratu aurretik. Tresna hauekin APIa egiaztatu ondoren, hurrengo urratsa gure kodetik API horretara Fetch API erabiliz sartzea da.
Datuak nabigatzailean biltegiratzea
57 Web Storage API
Web Storage API nabigatzaile moderno guztiek eskaintzen duten interfaze bat da, klabe-balio bikoteen bidez informazioa gordetzeko aukera ematen duena. Bi objektuk osatzen dute:
- localStorage
- sessionStorage
Bien funtzionamendua oso antzekoa da, eta desberdintasun nagusia datuak gordeta zenbat denboran mantentzen diren da.
57.1 klabe-balio sistemak
klabe-balio sistema baten funtzionamendua honako hauetan oinarritzen da:
- klabea: datua identifikatzeko erabiltzen dena da.
- balioa: lotutako informazioa dauka, hau da, interesatzen zaigun informazioa.
Gaur egun, sistema oso erabilia da, baita NoSQL datu-baseen sistemetan ere. Jarraian ikusiko ditugun sistemez gain, adibide batzuk baino ez ematearren:
- Redis: Memorian oinarritutako datu-base oso azkarra, cache gisa, saioak biltegiratzeko eta mezu-ilarak kudeatzeko erabiltzen dena.
- Valkey: Redis-en fork-a, 2024an egindako lizentzia-aldaketarekiko desadostasunengatik sortua.
- Memcached: Klabe-balioetan oinarritutako memoriako biltegiratze-sistema, batez ere web-aplikazioak bizkortzeko erabiltzen dena, aldi baterako datuak gordez.
- DragonFlyDB: Aurrekoekin bateragarria den sistema.
57.2 Gorde daitezkeen datuak
Bai localStorage-k bai sessionStorage-k testu-kateak soilik gordetzen dituzte. Zenbakiak, array-ak edo objektuak gorde nahi baditugu, aurretik JSON formatura bihurtu beharko ditugu.
Hurrengo taulan bien arteko desberdintasunen laburpena ikus dezakegu.
57.3 “Jatorri bereko” sarbidea
Gordetako datuak jatorri (origin) bereko orrietatik soilik eskura daitezke. Jatorria honako hauek osatzen dute:
- Protokoloa (http edo https)
- Domeinua
- Ataka
Adibidez, “https://www.ejemplo.com” helbidetik gordetako datu batek ezin izango ditu “https://midominio.com” helbidean gordetako datuak atzitu. Portaera hori nabigatzailearen segurtasun-politikaren parte da.
58 localStorage erabili
localStorage funtzioak informazioa nabigatzailean modu iraunkorrean gordetzeko aukera ematen du. Datuak eskuragarri egongo dira nabigatzailea itxi edo ordenagailua itzali ondoren ere. Honako kasu hauetan soilik desagertuko dira:
- Erabiltzaileak eskuz ezabatzen dituenean.
- Programak ezabatzen dituenean.
- Nabigatzailearen datuak garbitzen direnean.
58.1 Informazioa gorde
Datu bat gordetzeko, .setItem funtzioa erabili behar dugu. Bi parametro jasotzen ditu: klabe eta balioa. Balioa beti testu gisa gordeko da, zenbakia bada ere.
Informazioa localStorage erabiliz gordetzea
localStorage.setItem("nombre", "Alice");
localStorage.setItem("edad", 20); // "20"
Objektu bat gorde nahi badugu, JSON formatuan gorde beharko dugu JSON.stringify() erabiliz; bestela, datuak ez dira behar bezala gordeko:
Informazioa localStorage erabiliz gorde
const alumno = {
nombre: "Bob",
edad: 20
};
// Esto guardará "[object Object]"
localStorage.setItem("alumno", alumno);
// forma correcta
localStorage.setItem("alumno", JSON.stringify(alumno));
Objektu bat gorde nahi badugu, JSON formatuan gorde behar dugu JSON.stringify() erabiliz.
Funtzioa klabe berarekin berriro erabiltzen badugu, lehendik dagoen datua gainidatziko du.
Klabe bera erabiltzen badugu, lehendik dagoen datua gainidatziko du.
Orain, nabigatzailearen garatzaile-tresnen barruan “Application” edo “Biltegiratzea” fitxara joaten bagara, tokiko biltegiratze-atal bat dugula ikusiko dugu, balio honekin:
58.2 Informazioa irakurri
Informazioa irakurtzeko, klabea ezagutu behar da:
localStorage-ko informazioa irakurri
localStorage.getItem("nombre");
// para un objeto
const texto = localStorage.getItem("alumno");
const alumno = JSON.parse(texto);
console.log(alumno.nombre);
Objektu bat irakurri eta lortu nahi badugu, aurretik gordetako JSON testua parseatu behar dugu. Horretarako, JSON.parse() funtzioa erabiltzen da, eta objektu bat itzuliko digu. Ondoren, objektua erabili ahal izango dugu.
Objektu bat lortzeko, irakurritako testuarekin JSON.parse() erabili behar dugu.
58.3 Informazioa ezabatu
Berriro ere, datu bat ezabatzeko klabea ezagutu behar dugu.
localStorage-ko informazioa ezabatu
localStorage.removeItem("nombre");
Informazio guztia ezabatu nahi badugu, clear() funtzioa dugu. Jatorri horretako informazioa soilik ezabatuko du, baina kontuz erabili behar da.
localStorage-ko informazio guztia ezabatu
localStorage.clear();
clear()-ek jatorri horretako informazioa soilik ezabatzen du, baina kontuz erabili behar da.
58.4 Elementu kopurua lortzea
Gauden jatorrian zenbat elementu gordeta ditugun lor dezakegu:
localStorage-ko elementu kopurua lortu
localStorage.length;
58.5 klabeak lortu
Elementu kopurua jakinda, gordeta ditugun klabeak zeharkatu ditzakegu, edo haien izena balioarekin batera lor dezakegu.
localStorage-ko klabeak lortu
console.log(localStorage.key(0));
for (let i = 0; i < localStorage.length; i++) {
const clave = localStorage.key(i);
const valor = localStorage.getItem(clave);
console.log(clave, valor);
}
Erabili aurretik ikusitako localStorage-eko funtzioak datuak eta objektuak gordetzeko eta lortzeko.
59 sessionStorage erabiltzea
sessionStorage-ek localStorage-ek bezala funtzionatzen du ia, baina desberdintasun nagusia da informazioa nabigatzailearen uneko saioan soilik egongo dela eskuragarri. Fitxa edo leihoa ixten denean, datu guztiak automatikoki desagertzen dira.
sessionStorage erabiltzean, datuak fitxa edo leihoa ixtean desagertzen dira.
sessionStorage honako hauetarako erabil dezakegu:
- Hainbat urratseko laguntzaile baten datuak.
- Erosketa batean aldi baterako informazioa.
- Bilaketa baten emaitzak.
- Aldi baterako iragazkiak.
- Inprimaki baten tarteko datuak.
- Saioan zehar soilik mantendu behar diren hobespenak.
59.1 Informazioa gordetzea
Aurretik ikusitakoaren berdin funtzionatzen du.
Datuak sessionStorage erabiliz gorde
sessionStorage.setItem("pagina","inicio");
59.2 Informazioa irakurtzea
Informazioa irakurtzeko, klabea ezagutu behar da:
Informazioa sessionStorage erabiliz irakurri
sessionStorage.getItem("nombre");
59.3 Informazioa ezabatzea
Berriro ere, datu bat ezabatzeko klabea ezagutu behar dugu.
Informazioa sessionStorage erabiliz ezabatu
sessionStorage.removeItem("nombre");
// borrar todos
sessionStorage.clear();
61 localStorage, sessionStorage eta cookieen arteko konparaketa
Ikusi dugun bezala, nabigatzaile modernoek informazioa gordetzeko hainbat mekanismo eskaintzen dituzte, eta bakoitzak abantailak eta desabantailak ditu. Haien arteko desberdintasunak ezagutzeak egoera bakoitzerako irtenbiderik egokiena aukeratzeko aukera ematen du.
Hurrengo taulak laburpen gisa balio dezake:
| localStorage | sessionStorage | Cookies | |
|---|---|---|---|
| Iraunkortasuna | Iraunkorra | Saioan zehar soilik | Konfiguragarria |
| Gutxi gorabeherako tamaina | 5-10 MB | 5-10 MB | 4 KB |
| Zerbitzariari automatikoki bidaltzen zaio | Ez | Ez | Bai |
| JavaScriptetik eskuragarria | Bai | Bai | Bai (HttpOnly) cookieak izan ezik |
| Fitxen artean partekatua | Bai | Ez | Bai |
62 Segurtasuna
Mekanismo hauetako bat ere ez da erabili behar isilpeko informazioa gordetzeko. Beraz, inoiz ez litzateke erabili behar honelako datuak gordetzeko:
- Pasahitzak.
- Banku-txartelen zenbakiak.
- Informazio pertsonal sentikorra.
- klabe pribatuak.
Horregatik, aplikazio profesionalek informazio benetan garrantzitsua zerbitzarian gordetzen dute eta babes-mekanismo gehigarriak erabiltzen dituzte.
Aurretik aipatu dugu nabigatzaileek Same-Origin Policy (SOP) aplikatzen dutela; segurtasun-politika horrek web-orri batek beste domeinu bateko beste web-orri batek gordetako datuetara zuzenean sartzea eragozten du. Hala ere, babes horrek ez ditu datuak erabat eskuraezin bihurtzen. Erabiltzailearen ordenagailua programa maltzur batekin kutsatzen bada, nabigatzailearen luzapen batek gehiegizko baimenak lortzen baditu edo erasotzaile batek webgunearen barruan bertan kodea exekutatzea lortzen badu (adibidez, XSS eraso baten bidez), domeinu horrek gordetako informaziora sar daiteke.
Azken urteotan gai horri buruzko albisteak, session hijacking erabiliz: