View
152
Download
3
Category
Preview:
Citation preview
1
Core JavaScript Programming
Descrierea cursului Bazele programării JavaScript și programarea bazată pe limbajul C. Implementarea lui JavaScript în
HTML. Utilizarea practică a structurilor simple și complexe. Familiarizarea cu funcțiile integrate și
definite de utilizator. Bazele lucrului cu structura DOM. Implementarea și utilizarea bibliotecii jQuery.
Cerințe preliminare: Cunoștințe de bază de HTML şi CSS.
Scopul cursului Familiarizarea cursanţilor cu JavaScript și cu modul de implementare în HTML. Pregătirea utilizatorilor
pentru crearea paginilor web dinamice și pentru gestionarea evenimentelor. Dobândirea cunoștințelor
necesare pentru implementarea și folosirea bibliotecii jQuery.
Ce este JavaScript şi la ce se folosește?
Unitate: 1 din 19 00:17:25
+Rezumat
În cadrul acestei lecţii, facem cunoştinţă cu conceptele de bază ale tehnologiei JavaScript. Pentru
a ne familiariza în mod adecvat cu limbajul de programare JavaScript, mai întâi trebuie să ne
familiarizăm puţin cu modul de accesare a paginilor web prin internet şi cu modul de generare şi
afişare a acestora utilizatorului final.
Pentru a înţelege toate acestea, în primul rând trebuie să explicăm noţiunile de server, client şi
utilizator în procesul de emitere a unei pagini web. Prin urmare, server este programul care trimite
o pagină web clientului prin intermediul internetului; client este programul care traduce pagina în
formă grafică şi o afișează utilizatorului, în timp ce utilizatorul este, de fapt, persoana care inițiază
întregul proces atunci când dă clic pe un link sau când tastează o adresă în browser-ul său.
După ce am inițiat procesul, pe serverul web se generează pagina. Parser-ul (care se foloseşte
pentru decodare) citeşte marcajele (tags) de pe pagină şi gestionează conţinutul pe baza acestora.
Dacă întâlneşte un tag al unuia dintre script-urile de server (precum PHP, ASP, JSP), execută
script-ul aflat în tag-urile respective, iar apoi, după ce îşi termină sarcina, trimite pagina mai
departe către client. Tag-urile HTML şi tag-urile script-urilor de client nu se procesează pe server,
ci doar se trimit clientului, după care serverul nu mai are nicio influenţă asupra paginii.
Atunci când clientul deschide pagina, JavaScript are sarcina să decodeze conţinutul obţinut
(pagina) şi să-l afișeze utilizatorului. Dacă, în timpul parsării, aplicaţia de client (browser-ul)
întâlneşte script-ul de client (JavaScript), îl execută. Înseamnă că JavaScript este activ din
momentul în care pagina ajunge la client şi până în momentul în care pagina încetează să mai
existe pe client (când se trece la o altă pagină sau când se închide browser-ul). Din acest motiv,
JavaScript poate face tot ceea ce nu pot face script-urile de server, deoarece acestea sunt deja
executate în momentul în care pagina ajunge la client. De asemenea, oferă şi interacţiune directă
2
cu utilizatorul. În practică, JavaScript oferă suport animaţiilor, meniurilor derulante, casetelor cu
mesaje şi celorlalte elemente grafice dinamice, care alcătuiesc o pagină web.
Deşi deseori se fac confuzii între Java şi JavaScript, cele două au, de fapt, foarte puţine lucruri în
comun. Putem spune că cea mai mare similitudine dintre ele este cea de nume.
Imaginea 1.1. Java vs. JavaScript
În momentul în care în browser-ul Netscape (cel mai puternic browser din anii '90 ai secolului
trecut) s-a inclus suport pentru limbajul de programare Java, s-a modificat şi numele limbajului de
client din LiveScript în JavaScript. Prin urmare, similitudinea de nume se referă doar la această
inovaţie inclusă în browser-ul Netscape, nu şi la alte aspecte ale limbajului. Atunci când spunem
suport pentru Java în browser, subînţelegem posibilitatea de a activa Java Apple, o aplicaţie deja
tradusă care, în afara faptului că era implementată în HTML în formă încapsulată, nu avea nicio
legătură cu acesta (similar aplicaţiilor Flash). Pe de altă parte, JavaScript se află în interacţiune
directă cu HTML şi se interpretează în acelaşi timp cu HTML.
Nu în ultimul rând, în ceea ce priveşte denumirea, JavaScript este de fapt un sinonim pentru
limbajele care respectă standardul de limbaje ECMAScript (stabilit de către instituţia de
standardizare ECMA). Deşi funcţionează în acelaşi fel, în diferite browser-e aceste limbaje pot
avea nume diferite (și din anumite puncte de vedere, chiar pot funcţiona diferit). De exemplu, în
Microsoft Internet Explorer, acest limbaj se numeşte JScript. Funcţionalitatea diferită a
„dialectelor” dă programatorilor mari dureri de cap, deoarece uneori este necesară prelucrarea unui
bloc de cod într-un mod total diferit, în funcţie de browser.
Când JavaScript a apărut în anul 1995, scopul principal al acestuia era să execute validarea
elementelor de intrare, activitate care până atunci fusese lăsată în seama părţii de server. Netscape
a schimbat această abordare, prin introducerea lui JavaScript. Capacitatea de a susţine executarea
unor măsuri de bază ale validării pe partea de client a reprezentat un mare pas înainte în ceea ce
priveşte progresul tehnologiei de la acea vreme. Atunci, conexiunea la internet avea performanţe
foarte slabe, aproape incomparabile cu cele de astăzi. Trimiterea interogărilor către partea de server
pentru fiecare intrare de client nu era deloc un lucru practic, deoarece conexiunea la internet avea
o viteză foarte mică. De aceea, apariţia lui JavaScript a creat noi posibilităţi de procesare a datelor
pe partea de client, ceea ce a îmbunătăţit semnificativ performanţele site-urilor web.
3
De atunci, JavaScript s-a dezvoltat şi a devenit o caracteristică importantă a fiecărui browser
important de pe piaţă. Deşi la început JavaScript oferea suport doar pentru validarea elementelor,
caracteristicile acestuia s-au îmbunătăţit semnificativ odată cu versiunile ulterioare. Astfel, astăzi
avem un limbaj de programare JavaScript care ne permite interacţiunea cu aproape toate
caracteristicile pe care le posedă un browser, începând de la conţinut şi până la fereastra (window)
a browser-ului. JavaScript a fost recunoscut ca un limbaj de programare capabil să execute calcule
şi interacţiuni complexe, chiar şi metaprogramare.
JavaScript a devenit o parte foarte importantă a internetului, atât de importantă încât şi browser-
ele alternative, inclusiv cele de pe dispozitivele mobile, îl susțin. Nimeni nu avea să anticipeze
progresul rapid al limbajului JavaScript - de la un simplu validator al parametrilor de intrare până
la un adevărat limbaj de programare.
Scurt istoric
Pe măsură ce internetul devenea tot mai popular, a apărut nevoia unui limbaj de scripting pe partea
de client. La vremea aceea, majoritatea utilizatorilor de internet foloseau modemuri pentru
stabilirea conexiunii cu serverul, respectiv pentru accesarea unei anumite pagini web. Utilizarea
modemului a avut drept consecinţă îngreunarea fluxului de informaţii, în timp ce paginile web
deveneau tot mai complexe. Un alt dezavantaj era faptul că, pentru fiecare validare a unui element
introdus de utilizator, era necesară stabilirea unei conexiuni cu serverul și astfel se pierdea timp.
Netscape a început dezvoltarea unui limbaj de scripting cunoscut sub denumirea de Mocha care
mai târziu a devenit LiveScript. Odată cu lansarea versiunii Netscape Navigator 2, a început şi
prima implementare a acestui limbaj de scripting. Netscape a început colaborarea cu Sun
Microsystems, pentru a realiza întreaga implementare a lui LiveScript. Este publicată versiunea
JavaScript 1.0 care a avut un mare succes, apoi Netscape a dezvoltat repede după aceea şi o nouă
versiune 1.1, care a fost implementată în Netscape Navigator 3. La scurt timp după aceea,
Microsoft a decis să investească mai multe resurse în browser-ul Internet Explorer, aşadar, după
apariţia lui Netscape Navigator 3, Microsoft lansează Internet Explorer 3 în anul 1996, browser în
care a fost implementat JavaScript, cunoscut sub numele de JScript.
Condiţiile necesare pentru executarea lui JS
De executarea codului JavaScript este responsabilă aplicaţia de client. În majoritatea cazurilor,
este vorba de Internet Explorer, Firefox, Chrome, Opera sau Safari, în care utilizatorul este liber
să configureze executarea codului JavaScript sau chiar să-l dezactiveze complet. De aceea, trebuie
să avem grijă atunci când utilizăm JavaScript, deoarece se poate întâmpla ca utilizatorul să nu
dorească activarea acestuia, aşadar nu trebuie să limităm prin JavaScript utilizarea anumitor
elemente-cheie (de exemplu, să nu se poată executa un anumit control dacă nu există JavaScript şi
altele de acest gen). Inexistenţa lui JavaScript (oricât de rare ar fi cazurile) trebuie întotdeauna
anticipată atunci când îl utilizăm (de exemplu, prin încorporarea tag-ului Noscript). Astăzi, nu se
poate imagina utilizarea unui browser care nu are suport pentru JavaScript, dar, pe de altă parte,
utilizatorul poate exclude deliberat suportul pentru JavaScript în browser-ul său. După cum puteți
vedea, utilizatorul este reponsabil de rularea lui JavaScript (chiar îl poate citi și edita ușor), pentru
4
că în codul JavaScript nu trebuie să se introducă informații confidențiale, nici să se bazeze pe
validarea pe care JavaScript o oferă. În afară de aceasta, întotdeauna trebuie să se efectueze
validarea şi pe partea de server.
Condiţiile necesare pentru dezvoltarea aplicaţiilor JavaScript
Pentru a crea un cod JavaScript, nu avem nevoie de condiţii prealabile speciale. Codarea se poate
efectua şi în cel mai simplu editor de text. În cele mai frecvente cazuri, pentru codare se folosesc
aceleaşi instrumente ca şi pentru HTML (DreamWeaver, Visual Studio Notepad++).
Bineînţeles, există şi medii specializate pentru JavaScript, precum C-point JavaScript
editor (http://www.c-point.com/) sau Free JavaScript editor
(http://www.yaldex.com/Free_JavaScript_Editor.htm), Eclipse (cu JavaScript plug-in).
Noţiunea de programare
La fel ca majoritatea limbajelor de programare moderne, şi JavaScript are la bază limbajul de
programare C. Chiar dacă JavaScript se dezvoltă în proximitatea HTML-ului, modul lui de
funcţionare este total diferit.
Deşi JavaScript este foloseşte deseori ca sinonim pentru ECMAScript, JavaScript corespunde mai
degrabă cu ceea ce este definit prin ECMAScript. Întreaga implementare a lui JavaScript este
alcătuită din trei părţi separate: Core (ECMAScript), Document Object Model (DOM) şi Browser
Object Model (BOM), ceea ce putem vedea în figura de mai jos:
Imaginea 1.2. Core (ECMAScript), Document Object Model (DOM) şi
Browser Object Model (BOM)
ECMAScript este un limbaj definit de standardul ECMA – 262, care determină sintaxa, tipurile,
instrucţiunile, cuvintele-cheie, operatorii şi obiectele pe care le va folosi limbajul ECMAScript.
JavaScript reprezintă implementarea limbajului ECMAScript.
În primul rând, HTML nu este un limbaj de programare propriu-zis, ci un sistem de marcare prin
5
tag-uri a diferitor elemente din cadrul documentelor. De exemplu, dacă avem elementul:
<div>Conţinutul meu</div>, acesta nu face decât să-l anunțe pe cititor că pe pagină există un
element al cărui conţinut este „Conţinutul meu”. HTML este un simplu sistem de tag-uri, care nu
permite executarea unor acţiuni condiţionate în timpul scrierii conţinutului respectiv. De exemplu,
dacă am vrea ca doar cu ajutorul HTML-ului să-i spunem browser-ului să afişeze sub o anumită
condiţie un conţinut şi sub o altă condiţie un al doilea conţinut, nu am putea face acest lucru.
Spre deosebire de HTML, JavaScript controlează fluxul procesului şi formează o structură
dinamică, în funcţie de rezultate. Pentru a vedea cum funcţionează acesta, trebuie să ne
familiarizăm cu modul de bază al funcţionării unui limbaj de programare.
Caracteristica fiecărui limbaj de programare este gestionarea unor date prin executarea anumitor
operaţii asupra lor. În acest proces este important ca datele şi operaţiile să nu fie întotdeauna
identice, fiindcă doar astfel poate avea sens orice program. De aceea, de obicei, datele nu se fixează
în program, ci, la fel ca în cazul formulelor matematice, acestea sunt reprezentate prin variabile.
De exemplu, dacă programul nostru trebuie să adune două numere, acesta va realiza adunarea în
felul următor:
a=b+c
Trebuie ca, la începutul programului, să acordăm valori variabilelor b şi c, iar la sfârşitul
programului să afişăm valoarea variabilei a.
În afară de variabile, un rol foarte important în programare îl au şi condiţiile.
E puțin probabil că programul va fi funcţional, dacă nu are cel puţin o condiţie. Prin urmare, dacă
am fi vrut să afişăm rezultatul din exemplul precedent doar cu condiţia ca a să fie mai mare decât
zero, ar fi trebuit ca undeva să fi făcut o comparaţie a valorii variabilei a cu 0 şi, pe baza acesteia,
să decidem dacă vom emite sau nu rezultatul.
Următoarea caracteristică importantă a unui program este fluxul acestuia. Fiecare program are un
început şi un sfârşit (şi, bineînţeles, un conţinut). Important este ca, în fiecare moment al executării
programului, să ştim în ce parte a acestuia ne aflăm şi, de asemenea, să localizăm o anumită parte
a sa. Fluxul se poate controla (pe lângă condiţiile menţionate) şi cu diferite tipuri de bucle, când,
în funcţie de o condiţie, repetăm anumite părţi din cod de câteva ori, până la îndeplinirea condiţiei.
De exemplu, dacă am dori să afişăm de 10 ori cuvintele »programul meu«, am scrie următoarele:
a este 0
cât timp a este mai mic decât 10, realizează următorul lucru:
afişează propoziţia »programul meu«
măreşte a cu unu
6
Deseori, în program este nevoie să se repete de mai multe ori o anumită parte a acestuia, însă nu
în cadrul unui interval (aşa cum a fost cazul în exemplul de mai sus), ci doar în anumite locuri din
program. De exemplu, vrem să urmărim durata programului şi ca acesta să ne afișeze de mai multe
ori cât timp a mai rămas până la activarea lui. De exemplu:
începutul programului
ia timpul iniţial
fă operaţia unu
fă operaţia doi
...
ia timpul curent
scade timpul curent din timpul iniţial
emite rezultatul (diferenţa de timp) utilizatorului
fă operaţia trei
fă operaţia patru
...
ia timpul curent
scade timpul curent din timpul iniţial
emite rezultatul (diferenţa de timp) utilizatorului
În acest exemplu, blocul care preia timpul curent se repetă de două ori, prin scăderea timpului
curent din cel iniţial (obţinerea diferenţei de timp) şi prin emiterea rezultatului utilizatorului.
Având în vedere că în programare este valabilă regula conform căreia nimic nu trebuie să se repete,
astfel de blocuri trebuie localizate în secţiuni separate şi trebuie apelate în fiecare moment în care
avem nevoie de ele. Secţiunile se numesc, de obicei, funcţii (în unele limbaje, acestea se mai
numesc şi proceduri).
În cazul funcţiei, acelaşi program ar arăta astfel:
începutul programului
funcţia diferenţă de timp
ia timpul iniţial
fă operaţia unu
fă operaţia doi
...
porneşte funcţia diferenţă de timp
fă operaţia trei
fă operaţia patru
...
porneşte funcţia diferenţă de timp
Acest program, în afara faptului că este mai scurt, deşi au avut loc mai multe apelări ale aceleiaşi
7
funcţii, oferă şi posibilitatea de a modifica fiecare calcul al diferenţei de timp într-un singur loc.
Nu încercați să reţineţi în acest moment ordinea de scriere a declarației, pentru că ne vom ocupa
de sintaxă în lecțiile următoare. Acum este important să înțelegem logica pe care ar trebui să o
folosim atunci când se scriu programe.
Implementarea codului JavaScript în HTML
Unitate: 2 din 19 00:14:19
+Rezumat
În această lecție, ne familiarizăm cu modul de implementare a lui JavaScript. Toate limbajele script
referitoare la crearea şi manipularea paginilor web sunt încorporate, de obicei, în codul HTML, iar
JavaScript nu face excepţie de la această regulă. Cu toate acestea, atunci când implementăm
JavaScript pe o pagină, trebuie să avem în vedere anumite caracteristici ale paginii, respectiv ale
emiterii acesteia.
De aceea, este necesar ca, înainte de a începe să scriem orice cod JavaScript, să determinăm unde
ar trebui să plasăm codul HTML și cum să-i explicăm browser-ului să interpreteze codul exact ca
JavaScript și nu ca HTML sau orice alt limbaj.
Există câteva moduri în care clientul JavaScript poate fi integrat în HTML:
între tag-urile <script> şi </script>;
prin introducerea codului dintr-o sursă externă;
prin procedura de procesare a evenimentului, specificat ca o valoare a atributului HTML.
Implementarea codului JavaScript între tag-urile <script> şi </script>
Pentru a implementa JavaScript pe pagină, trebuie să evidențiem începutul şi sfârşitul script-ului
introducând tag-uri:
1 <script></script><span style="font-size: 14px; text-align: justify;"> </span>
O astfel de declaraţie a tag-urilor pentru JavaScript va funcţiona fără probleme în documentele
HTML 5, fiindcă de la această versiune JavaScript se consideră limbajul script implicit pe pagină.
Pentru a fi siguri că acest cod va funcţiona şi în versiunile anterioare ale lui HTML, vom seta
atributul type:
1 <scripttype="text/javascript"></script><span style="font-size: 14px; text-
align: justify;"> </span><span style="font-size: 14px;"> </span>
8
Notă: Mai devreme, am folosit atributul language=”JavaScript”, care acum este considerat învechit și
nu mai trebuie folosit.
Pentru a verifica dacă implementarea codului funcționează, pe pagină în interiorul tag-urilor
<script> vom scrie o linie de cod JavaScript pe care încă nu o cunoașteți, dar de care avem nevoie
pentru a obține o ieșire pe pagină:
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
<title>First page</title>
</head>
<body>
<script type="text/javascript">
alert('Hello!');
</script>
</body>
</html>
Linia alert('Hello!'); reprezintă partea din codul JavaScript care afișează fereastra alert cu mesajul
specificat între ghilimele și cu butonul OK. Trebuie avut în vedere faptul că această comandă
specificată în cod va fi executată atunci când codul se va descărca, de unde deducem că este foarte
important unde vom plasa codul JavaScript, temă despre care vom discuta în continuare.
Codul JavaScript se poate iniţializa cu tag-urile script de câte ori vrem pe pagină.
De exemplu:
1
2
3
4
<head>
<script type="text/javascript" >
document.write("JavaScript - HEAD");
</script>
</head>
9
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<body>
<h1>Some text 1</h1>
<script type="text/javascript" >
document.write("JavaScript - BODY 1");
</script>
<p>Some text 2</p>
<script type="text/javascript" >
document.write("JavaScript - BODY 2");
</script>
<p>End of Document</p>
</body><span style="font-size: 14px; text-align: justify;"> </span>
Acest cod va fi citit secvenţial, iar rezultatul afișat pe pagină va fi:
10
Imaginea 2.1.
O parte a codului JavaScript, document.write("JavaScript - HEAD"); , se foloseşte pentru a scrie
textul specificat între ghilimele pe pagină. Observaţi cum sunt executate comenzile în momentul
în care au fost încărcate. Veți vedea că în secțiunea Head se află comanda care scrie un text pe
pagină. Aici, am postat aceasta pentru a arăta teoretic când și cum se execută codul JavaScript, dar
trebuie să ştiți că nu vă recomandăm să postați în secțiunea Head un cod JavaScript care afișează
ceva pe pagină, ci este preferabil să faceți acest lucru în cadrul tag-ului body.
Deși codurile JavaScript se scriu între tag-uri separate <script> în document, ele încă fac parte din
același program JavaScript, astfel încât să fie părți ale codului definite într-un tag disponibil şi
unul <script>. Priviți exemplul:
1
2
3
4
5
<head>
<script type="text/javascript" >
var x = 10;
</script>
</head>
<body>
11
6
7
8
9
10
<script type="text/javascript" >
document.write(x);
</script>
</body><span style="font-size: 14px; text-align: justify;"> </span>
Partea codului JavaScript var x = 10; serveşte la definirea variabilei x, care are valoarea 10.
După cum vedeţi în tag-ul <script> care se află în partea Head, am declarat variabila x şi i-am
acordat valoarea 10. După aceasta, în partea Body am deschis un nou tag <script> şi aici am
accesat variabila x.
Introducerea unui cod JavaScript dintr-o sursă externă
Uneori, funcţionalitatea script-ului este atât de mare, de compactă şi încapsulată, încât este mai
bine să o păstrăm în afara documentului HTML. În acest caz, script-urile se salvează extern şi se
încarcă în document la nevoie. De exemplu, dacă avem un script care conţine o funcţie generală,
aceasta nu trebuie să existe pe fiecare pagină. Pe pagina care necesită script-ul putem încărca
fişierul extern în care se află acesta.
Tag-ul <script>, despre care am vorbit deja, susține atributul src cu care putem să definim URL-
ul fişierului care conţine codul necesar în pagina respectivă.
Să vedem un exemplu. În primul rând, putem crea un fişier index.html şi în cadrul documentului
să scriem următorul cod:
1
2
3
4
5
6
<head>
<title>Page 1</title>
</head>
<body>
<script type="text/javascript" src="popup.js"></script>
</body>
Utilizând atributul src, includem fişierul extern cu numele popup.js, pe care trebuie să-l creăm în
același folder în care am creat și index.html.
12
Acum, putem crea şi fișierul extern JavaScript cu numele popup.js, iar în cadrul acestuia să plasăm
următorul cod simplu:
1 alert('Hello');<span style="font-size: 14px; text-align: justify;"> </span>
Când pornim index.html, codul din fișierul extern se execută.
Conform convenției stabilite, fişierele JavaScript externe se denumesc cu extensia .js, însă acest
lucru nu este obligatoriu pentru ca scriptul să funcţioneze. Fişierul extern poate fi denumit cu orice
extensie, atâta timp cât numele fişierului este scris corect în atributul src al iniţializării script-
ului. De asemenea, aşa cum puteţi observa în cazul fişierului extern JavaScript nu sunt necesare
tag-urile <script> , scrierea codului începe imediat.
Utilizarea fișierelor externe JavaScript nu este o soluție bună dacă este vorba de un cod mic care
se utilizează doar pe o singură pagină. În acest caz, este mai bine să scriem codul în tag-urile
<script> pe acele pagini pe care este nevoie. Totuşi, utilizarea fișierelor externe poate avea
numeroase avantaje foarte importante:
Uneori, codul JavaScript este atât de mare și de voluminos, încât este mai bine să-l separăm
de HTML și să mărim transparența.
Sunt frecvente cazurile în care o funcție sau o altă parte din codul JavaScript foloseşte mai
multe pagini HTML. Dacă nu am avea posibilitatea să includem același fișier extern, am fi
obligaţi să copiem același cod pe fiecare pagină. O problemă și mai mare ar apărea dacă
am dori să modificăm o parte din cod. Ar trebui să verificăm fiecare fișier HTML care
foloseşte același cod și să efectuăm schimbările peste tot, în timp ce, dacă utilizăm fișierul
extern, efectuăm modificarea doar într-un singur document.
Atunci când plasăm codul JavaScript care se utilizează pe mai multe pagini într-un fişier
separat, permitem caching-ul acelui fişier, ceea ce poate reduce timpul de încărcare a
paginii şi poate îmbunătați performanţa.
În felul acesta, putem folosi fişierele externe care se află pe alte servere. Această
posibilitate se foloseşte frecvent pentru a face reclamă pe internet.
Implementarea codului JavaScript prin procedura de procesare a evenimentului
Codul JavaScript, pe care l-am scris până acum, se execută în momentul în care se încarcă HTML.
Este clar că un astfel de comportament nu este în măsură să ofere un grad mai înalt de dinamism
paginii, deoarece utilizatorul nu poate influenţa încă executarea codului. De aceea, putem
defini evenimentele care vor iniția executarea unei părți din codul JavaScript. Astfel, putem asculta
dacă utilizatorul a dat clic pe un buton de pe pagină, a trecut cu mouse-ul peste un câmp, a apăsat
pe un buton de pe tastatură etc., iar pe baza aceasta vom defini acțiunea. Despre aceste evenimente
vom discuta în detaliu în lecțiile următoare. Pentru moment, este suficient să dăm un exemplu
simplu de executare a codului JavaScript, după ce dăm un clic cu mouse-ul pe un text.
Exemplu:
13
1
2
3
4
5
6
<head>
<title>Page 1</title>
</head>
<body>
<p onclick="alert('Hi!')">Click Me</p>
</body><span style="font-size: 14px; text-align: justify;"> </span>
Ca valoare a atributului onclick, am introdus codul JavaScript, care se execută după ce dăm clic
pe tag-ul p. De asemenea, putem scrie mai multe comenzi într-un singur apel, dar în acest caz
comenzile trebuie să fie separate prin semnul ;.
1 <p onclick="alert('Hello!'); alert('Hello, again!')">Click Me</p>
Notă: Foarte frecvent, programatorii consideră că aceste atribute pentru evenimente nu ar trebui să fie
folosite în general, ci ar trebui să definească întotdeauna ascultătorii de evenimente în codul
JavaScript. Despre aceşti ascultători, vom discuta în lecțiile următoare. O astfel de abordare ne
permite să separăm complet conținutul de comportament. Conform acestui lucru, tot conținutul lui
JavaScript ar trebui să fie stocat într-un fișier extern.
Ascunderea script-urilor în cazul în care browser-ul nu permite JavaScript
În timpul dezvoltării timpurii a lui JavaScript, unele browser-e nu erau capabile să recunoască și
să execute codul. Dacă am fi vrut să-l afișăm pe pagină, codul JavaScript ar fi fost afișat ca un text
simplu. Pentru a preveni un astfel de comportament, programatorii au pus codurile JavaScript între
tag-uri HTML pentru comentarii, astfel încât codul, în cazul în care browser-ul îl susține, să
funcționeze fără probleme, iar dacă browser-ul nu recunoaște script-ul, vede semnele de comentare
a codului, iar acesta nu îl afișează pe pagină.
De exemplu:
1
2
3
4
5
6
7
<head>
<title>Page 1</title>
</head>
<body>
<script type="text/javascript"><!--
document.write("Hello!");
//--></script>
14
8 </body><span style="font-size: 14px; text-align: justify;"> </span>
Totuşi, astăzi aproape nimeni nu mai folosește astfel de browser-e învechite, deci nu trebuie să ne
mai facem griji. Dar, în continuare există posibilitatea ca utilizatorul să oprească intenționat
JavaScript-ul din browser-ul său. Deoarece această posibilitate există dintotdeauna, nu ar trebui să
permitem ca aceste componente vitale ale paginii să depindă de JavaScript. Ar fi ideal dacă toate
componentele paginii ar funcționa şi fără JavaScript sau JavaScript ar fi acolo doar pentru a
îmbunătăți experiența pe site a utilizatorului. Totuşi, dacă aşa ceva nu este posibil, trebuie să
utilizăm tag-urile <noscript>. Conținutul dintre aceste tag-uri s-ar afișa numai în cazul în care în
browser nu ar exista niciun suport pentru JavaScript. De aceea, această metodă se foloseşte cel mai
frecvent pentru ca în cadrul acestor tag-uri să se plaseze mesajul care va informa utilizatorul că e
nevoie să activeze JavaScript pe browser-ul său, pentru a utiliza toate elementele paginii. De
asemenea, aici poate fi setat și un link către o altă pagină, special concepută să funcționeze fără
JavaScript.
De exemplu:
1
2
3
4
5
6
7
8
9
<head>
<title>Page 1</title>
</head>
<body>
<script type="text/javascript">
document.write("Hello!");
</script>
<noscript><p>Browser not support javascript.</p><a href="#">Please Click
Here..</a></noscript>
</body><br><br><span style="font-size: 14px; text-align: justify;"> </span>
Activarea/dezactivarea lui JavaScript în browser-ul Google Chrome
16
Imaginea 2.4.
Imaginea 2.5.
Structura lexicală
Unitate: 3 din 19 00:17:37
+Rezumat
În cadrul acestei lecţii, învăţăm despre bazele sintaxei care se aplică în limbajul JavaScript. Spre
deosebire de limbajele de programare de nivel inferior, limbajele de scripting, nu implică de obicei
o mare stricteţe în ceea ce priveşte sintaxa şi convenţiile. Acest lucru se datorează faptului că
limbajele de nivel inferior (limbajele în care se execută programele în sine) se folosesc pentru
comunicarea dintre utilizator şi calculator, în timp ce limbajele de scripting se folosesc pentru
comunicarea dintre utilizator şi program. Cel mai redus nivel de sintaxă a unui limbaj de
programare se numește structura lexicală și, de aceea, aici vom stabili regulile de bază care trebuie
urmate atunci când scriem codul JavaScript.
În ceea ce privește JavaScript, am menţionat deja că este vorba de un derivat al limbajului de
programare C – ceea ce înseamnă că majoritatea sintaxei a fost preluată de acolo.
Programele JavaScript sunt alcătuite din instrucţiuni grupate într-un bloc. Aceste instrucţiuni din
cadrul programului JavaScript îi spun interpretului să execute una sau mai multe acţiuni.
Instrucţiunile JavaScript pot fi simple sau complexe, la fel ca şi în alte limbaje de programare. În
program, o instrucțiune este alcătuită dintr-un set de operatori, simboluri şi identificatori grupaţi
pentru ca, împreună, să creeze o entitate pe care interpretul JavaScript o înţelege.
17
Reguli de scriere a identificatorului
Identificatorii sunt nume cu care denumim variabile, funcții sau specificăm labels (etichetele),
despre care vom discuta în următoarele lecții. Pentru moment, este important să știm că există
reguli care trebuie respectate pentru a defini corect identificatorul. Regulile de formare corectă a
numelui identificatorilor sunt aceleași în JavaScript ca în Java. Primul semn trebuie să fie:
litera;
liniuța de jos (_);
semnul dolarului ($).
Fiecare semn ulterior poate fi o literă, o liniuță de jos, semnul dolarului sau un număr. Este
important să reţinem că numărul nu ar trebui să fie pe primul rând. Iată câteva exemple de
identificatori corecţi pe care îi putem utiliza, de exemplu, pentru a defini variabile noi:
x ;
person ;
person1 ;
person_1 ;
_person ;
$person .
Liniile (declaraţiile)
O regulă frecventă a sintaxei de programare este că fiecare linie de cod trebuie să se încheie cu
semnul ; (punct şi virgulă). Această regulă este valabilă pentru JavaScript doar parţial. De fapt, în
JavaScript nu este obligatoriu să încheiaţi o linie cu punct şi virgulă, acest lucru fiind opţional, iar
absența acestui semn nu va afișa nicio eroare în browser. Dar această convenţie de programare este
atât de puternică, încât va fi foarte greu să întâlniţi JavaScript fără punct şi virgulă la sfârşitul liniei:
1 var x=1;
De asemenea, dacă dorim să specificăm mai multe comenzi într-o singură linie de cod, trebuie să
le separăm prin semnul ;
1 <script>document.write('Text1'); document.write('Text2')</script><span
style="font-size: 14px; text-align: justify;"> </span>
Cuvintele-cheie se folosesc pentru a defini o activitate care trebuie preluată în acel moment.
Cuvântul-cheie var îi transmite browser-ului că trebuie să creeze o variabilă nouă. Numele
variabilei trebuie definit doar cu ocazia declarării variabilei. De fiecare dată când vom avea nevoie
18
de o variabilă definită, o apelăm specificând numelui complet al variabilei, fără niciun fel de
cuvânt-cheie în față:
1
2
var x=1;
document.write(x);<span style="font-size: 14px; text-align:
justify;"> </span>
După cum puteți vedea în acest exemplu, mai întâi am definit variabila x, scriind în fața ei cuvântul-
cheie var. Am profitat de ocazie și în aceeași linie de cod i-am atribuit valoarea 1, deși am fi putut
face şi în felul următor:
1
2
3
var x;
x = 1;
document.write(x);
După ce definim variabila, o folosim prin specificarea numelui ei; deci, nu specificăm cuvântul-
cheie var. Observaţi că vom folosi cuvântul-cheie var atunci când definim variabila x; totuşi,
acestei variabile nu i-am atribuit încă o valoare. Este clar că variabilele au scopul de a păstra un
conținut sau o valoare. Pentru a atribui o valoare unei variabile, utilizăm operatorul de atribuire,
respectiv semnul egal, urmat de specificația literal, care este singura valoare, iar la scriere există
reguli:
numărul poate fi scris ca o valoare întreagă -> 10 sau ca o zecimală 10.123;
textul se scrie între ghilimele simple -> 'Simple text' sau ghilimele duble -> "Simple text";
valoarea fixă poate fi reprezentată și de expresiile -> 10+5.
Notă:
Putem defini mai multe variabile într-o singură declaraţie. Începem declaraţia cu cuvântul-cheie
var, iar apoi specificăm variabilele separate prin virgule:
1 var x = 5, y = 10, z = 20;<span style="font-size: 14px; text-align:
justify;"> </span>
Dacă vă întrebați de ce trebuie să declarăm o variabilă, deși deja putem să o folosim și fără
declarație, unul dintre răspunsuri este că știm că o anumită variabilă ne va fi necesară în
instrucțiunile pe care le vom executa, dar încă nu știm ce valori vom gestiona.
Odată cu declaraţia variabilei, nu trebuie să folosim o valoare, ci îi putem atribui şi rezultatul
declaraţiei întregi. De exemplu:
1 var x = 2+3;
19
Informații suplimentare despre semnul opțional ;
Codul pe care îl scrieţi în JavaScript este vizibil pe pagina web şi tocmai de aceea este bine să daţi
dovadă de cât mai multă meticulozitate în munca dvs., aşadar vă recomandăm să încheiați linia cu
punct şi virgulă.
În JavaScript, la fel ca şi în majoritatea altor limbaje de programare, există cazuri în care nu avem
voie să punem punct şi virgulă la sfârşitul instrucţiunii. Semnul punct şi virgulă nu trebuie introdus
în niciun caz în bucle şi în ramificările condiţionate. Această regulă există deoarece, în timpul
definirii condiţiilor şi a buclelor, conţinutul instrucţiunii se va executa - acest lucru este implicit.
Când definiţi condiţia, se presupune că veţi defini și la ce instrucţiuni se va referi aceasta. Condiţia
în sine nu are niciun sens dacă nu conţine instrucţiuni la care să se refere. De exemplu, aceasta este
o instrucţiune incorectă:
1
2
if(x==2);
document.write(x);
Instrucţiunea se va executa, însă definirea ei nu condiţionează nimic. Cu alte cuvinte, nu conţine
blocul cu instrucţiuni care se vor executa dacă este îndeplinită condiţia sau dacă nu este îndeplinită.
Mai multe detalii despre condiţii şi ramificare veți găsi într-una dintre lecţiile viitoare, unde vom
învăţa cum putem defini corect o condiţie şi instrucţiunile din cadrul ei. În momentul de faţă, este
suficient să ştim că semnul punct şi virgulă nu ar trebui pus la sfârşitul instrucţiunii if().
Blocurile
Când pe o pagină există un cod JavaScript, browser-ul trece prin el şi pornește liniile acestuia pe
rând. Noţiunea de cod JavaScript implică o secvenţă de linii JavaScript organizate într-un bloc.
Dar ce este un bloc? În acest caz, un bloc este orice secvenţă continuă de linii JavaScript. Spre
deosebire de codul complet, blocul poate fi alcătuit dintr-una sau mai multe linii JavaScript,
încadrate într-un cod JavaScript.
De exemplu, avem următorul cod:
1
2
3
4
var a=1;
var b=2;
var c=a+b;
document.write(c);
Pur şi simplu, am putea să spunem că liniile 3 şi 4 din codul precedent reprezintă un bloc care
calculează şi emite valoarea c.
20
Pentru ca un calculator să poată înregistra un cod sub formă de bloc separat, acesta trebuie introdus
între paranteze acolade:
1
2
3
{
//acesta este un bloc
}
Blocul de cod din exemplul precedent, în afara funcţiei de afișare, nu are nicio altă funcţie,
deoarece codul din cadrul blocului va fi întotdeauna executat.
Pentru ca blocul să aibă un rol în cadrul programului, executarea conţinutului său trebuie să fie
condiţionată:
1
2
3
4
//conditie
{
//acesta este un bloc
}<span style="font-size: 14px; text-align: justify;"> </span>
Despre modul în care se defineşte condiţia și ce s-ar putea găsi într-un bloc de cod vom discuta în
lecțiile următoare. Pentru moment, trebuie să știţi ce sunt blocurile de cod și cum sunt indicate.
Case sensitivity
JavaScript este, de asemenea, şi un limbaj de programare case sensitive, ceea ce înseamnă că va
trata în mod diferit elementele scrise cu majusculă şi minusculă:
1 var A=10;
nu este același lucru cu:
1 var a=10;
De asemenea, trebuie să fim atenţi atunci când apelăm anumite cuvinte-cheie, pentru ca acestea să
se execute. De exemplu, condiţia if nu este acelaşi lucru cu IF. Dacă greşiţi atunci când introduceţi
denumirea cuvântului-cheie, instrucţiunea nu se va executa aşa cum doriţi şi va semnala o eroare.
În acest caz, JavaScript nu va recunoaşte că este vorba de un cuvânt-cheie, care se comportă într-
un anumit mod, aşadar instrucţiunea se va executa diferit. Toate cuvintele-cheie se scriu cu
minuscule. Excepţie fac variabilele pe care le definiţi singuri, aşa-numitele variabile definite de
utilizator. În timpul definirii variabilelor, aveţi libertatea să combinaţi majuscule şi minuscule aşa
21
cum doriţi. Ceea ce este important când apelăm o variabilă definită este să menţinem denumirea
neschimbată. De exemplu:
1
2
var HoLa="Hola";
document.write(HoLa);<span style="font-size: 14px; text-align:
justify;"> </span>
După cum puteţi concluziona, în limbajul JavaScript totul este case sensitive, începând de la
variabile până la operatori şi denumirea funcţiilor.
Comentariul codului
Dacă vrem ca un conţinut să fie memorat în codul-sursă, dar fără ca acest conţinut să influenţeze
executarea programului, folosim comentarea codului. Comentariile permit codului să fie mai uşor
de revizuit şi mai clar. Chiar dacă definim codul la un moment dat cu comenzile de executare a
instrucţiunilor evidente, este posibil ca aceste instrucţiuni să nu ne mai pară atât de evidente data
viitoare când analizăm codul, în special dacă a trecut ceva timp de când l-am scris. De aceea,
recomandăm comentarea liniilor de cod, fiindcă prin comentarii putem explica la ce se foloseşte
fiecare instrucţiune din cadrul blocului. Comentariile sunt foarte utile pentru a explica niște lucruri
pe care să le poată înţelege şi alte persoane. În JavaScript, codul se poate comenta într-o singură
linie de cod sau ca un întreg bloc de instrucţiuni la un loc, lucru pe care îl vom vedea într-un
exemplu concret în continuarea acestei lecţii.
Nu există niciun limbaj de programare fără opţiunea de comentare a codului, aşadar nici JavaScript
nu face excepţie din acest punct de vedere.
Există multe cazuri în care comentarea codului reprezintă o nevoie practică:
Crearea notelor de observaţie în timpul dezvoltării codului. În codurile mari este foarte
uşor să vă pierdeţi în detalii. De aceea, trebuie întotdeauna să comentați unităţile logice ale
codului, pentru ca în orice moment să aveţi notiţe care să vă reamintească la ce servesc
anumite părţi din cod.
Un cod bine comentat facilitează munca programatorului care moşteneşte codul respectiv.
De aceea, întotdeauna recomandăm comentarea codului în timpul muncii în echipă.
Veţi manipula mai uşor şi mai repede funcţionalităţile codului. Aceasta înseamnă că putem
dezactiva anumite părţi din cod (să le transformăm în comentariu) sau să le activăm (să
eliminăm comentariul). Dacă programul nostru conţine 100 de linii de cod pe care am vrea
să le dezactivăm pentru moment (însă nu să le ştergem), cel mai simplu mod este să le
comentăm.
Comentarea unei linii de cod
22
Dacă dorim ca în codul nostru să adăugăm un comentariu care se află doar pe o linie de cod,
putem să punem la începutul textului semnul pentru comentariu // .
1
2
//acesta este comentariul codului
var a=1;
Când îl vom porni, programul se va executa fără nicio problemă şi va acorda o valoare variabilei
a. Totuşi, linia de cod pe care am marcat-o ca şi comentariu nu va fi afișată pe pagină, dar o putem
vedea atunci când deschidem Page Source.
Comentariul se poate adăuga şi după linia de cod, de exemplu:
1 document.write("Hello"); //my comment
Totuşi, trebuie să avem grijă la faptul că, deşi comentariul este invizibil pentru interpret, acesta
este uşor vizibil pentru utilizator (la fel ca întregul cod JavaScript), aşadar trebuie evitate
comentariile sau notiţele personale atunci când codul trece în mediul de producţie.
Comentarea blocului de cod
Dacă vrem să comentăm mai multe rânduri/linii (un bloc), putem comenta fiecare rând separat:
1
2
//primul rând al comentariului
//al doilea rând al comentariului
sau putem crea un aşa-numitul bloc de comentariu:
1
2
3
/*
acesta este un bloc de comentariu
*/
unde marcajul /* începe blocul de comentariu, iar marcajul */ îl încheie. Fiecare text aflat între
aceste două marcaje va fi tratat ca un comentariu.
Spaţiul gol
Trebuie să ştim că liniile de cod JavaScript nu sunt analoage liniilor de cod HTML, ceea ce
înseamnă că, dacă trecem pur şi simplu pe un nou rând JavaScript, nu înseamnă că în mod automat
23
trecem şi pe un rând nou HTML (respectiv că pe pagina web se va afişa că am trecut pe un nou
rând).
Pentru codul:
1
2
document.write("Hello!");
document.write("Hello again!");
rezultatul pe pagina web va fi următorul:
1 Hello!Hello again!
Dacă am dori ca rezultatul să fie analog liniilor de cod, rezultatul de mai sus nu ar fi valid. Pentru
a obţine ca textul să fie afişat pe două rânduri, în string-urile respective trebuie să introducem şi
un tag HTML adecvat pentru noul rând:
1
2
document.write("Hello!<br>");
document.write("Hello again!");<span style="font-size: 14px; text-align:
justify;"> </span>
Pe pagina web, un astfel de cod ar fi dat un rezultat adecvat:
1
2
Hello!
Hello again!
Totuşi, să privim acelaşi exemplu, cu diferenţa că valorile specificate între ghilimele vor fi plasate
în variabile:
1
2
3
4
var h1 = "Hello!";
var h2 = "Hello again!";
document.write(h1);
document.write(h2);<span style="font-size: 14px; text-align:
justify;"> </span>
Rezultatul de pe pagină este: Hello!Hello again!
Pentru a nu folosi de două ori funcţia write, putem efectua unirea sau concatenarea string-urilor
plasate în variabilele h1 şi h2. În JavaScript (ca şi în Java) o astfel de unire se efectuează cu ajutorul
operatorului + , aşa cum este prezentat în acest exemplu:
24
1
2
3
var h1 = "Hello!";
var h2 = "Hello again!";
document.write(h1 + h2);<span style="font-size: 14px; text-align:
justify;"> </span>
Rezultatul de pe pagină a rămas neschimbat. Totuşi, lipseşte spaţiul între primul şi al doilea text.
Deoarece aceasta nu este o practică bună, și anume adăgarea unui spațiu în variabila în sine, putem
face o altă concatenare, după cum urmează:
1
2
3
var h1 = "Hello!";
var h2 = "Hello again";
document.write(h1 + " " + h2);
Tipurile de date, variabilele și constantele
Unitate: 4 din 19 00:23:11
+Rezumat
În cadrul acestei lecţii, ne vom familiariza cu principalele tipuri de date, cu variabilele şi cu
constantele care se pot aplica în limbajul JavaScript.
JavaScript deosebeşte, în general, 5 tipuri principale de date:
Tip Exemplu / Explicaţie
Number 42, 3.14159
Logical (Boolean)
true / false
String "Un text"
null null este o valoare specială, care indică inexistenţa oricărei valori concrete. Având în vedere că
JavaScript este case sensitive, null nu este la fel ca iNull, NULL sau oricare altă variantă.
undefined undefined este o valoare specială, care se foloseşte atunci când încercăm să folosim variabila
care este declarată, dar căreia nu îi este atribuită o valoare.
Tabelul 4.1. Principalele tipuri de date
25
După ce ne-am familiarizat cu aceste tipuri, trebuie să menționăm că în JavaScript există şi obiecte
și funcții. Deși vom procesa și utiliza obiectele mai târziu, pentru moment imaginați-vi-le ca pe o
cutie în care putem stoca mai multe valori, dar şi funcționalităţi, în timp ce pe funcții imaginați-le
ca diferite activități (funcționalităţi) pe care aplicaţia noastră le poate executa.
Notă:
În funcție de clasificare, putem spune că JavaScript recunoaște tipuri primare sau primitive:
String, Number şi Boolean, tipuri de compoziţie sau de referință: Object și Array şi tipuri de date
speciale: Null şi Undefined.
Numere (Numbers)
Unul dintre cele mai simple tipuri de date pe care JavaScript le susţine sunt, desigur, numerele.
Dacă celelalte limbaje de programare vă sunt deja familiare, cum ar fi, de exemplu, limbajul C,
atunci deja ştiţi că aceste limbaje fac diferenţa între valorile întregi (0,3,10,256 etc.) şi zecimale
(0.5,10.065 etc.). Totuşi, JavaScript nu face diferenţa între valorile întregi (integers) şi cele cu
virgulă mobilă (floating-point values). Asta nu înseamnă că nu puteţi folosi astfel de numere; din
contră, le puteţi folosi chiar mai uşor decât în Java sau limbajul C, dar JavaScript le va privi ca un
tip Number.
Când definim o variabilă şi îi atribuim valoarea unui număr, spunem că variabila creată este de tip
Number:
1 var x = 10;
În cazul nostru, variabila x este de tip Number. Totuşi, numerele se pot găsi în cod ca o parte a
unei formule matematice, iar numerele astfel specificate în cod se numesc literali numerici.
În faţa literalilor numerici, putem seta operatorul unar care marchează dacă este vorba de un număr
negativ.
Numerele foarte mari sau foarte mici se pot scrie cu ajutorul unei notaţii exponenţiale speciale:
1
2
var x = 256e5; // 25600000
var y = 256e-5; // 0.00256
Valorile numerice speciale NaN şi Infinity
După unele operații matematice „neregulate”, cum ar fi, de exemplu, împărţirea lui 0 la 0, în
rezultat apare valoarea specială NaN (Not-a-Number). Această valoare este foarte specifică,
26
deoarece nu se poate compara cu niciun număr, nici chiar cu ea însăşi. Acest lucru este important
de ştiut atunci când ne vom ocupa de controlul fluxului. Dacă vrem să verificăm dacă o variabilă
are valoarea NaN, trebuie să folosim funcţia isNaN():
1 var x = 0 / 0;<span style="font-size: 14px; text-align: justify;"> </span>
În acest exemplu, variabila x va avea valoarea NaN.
JavaScript se comportă la fel şi în cazul în care, de exemplu, încercăm să împărțim cu 0 un număr
care nu este 0, doar că, în acest caz, rezultatul va fi o altă valoare numerică specială Infinity:
1 var x = 5 / 0;
În acest exemplu, variabila x va avea valoarea Infinity.
Infinity poate marca şi un număr infinit negativ:
1 var x = -5 / 0;
În acest exemplu, variabila x va avea valoarea -Infinity.
Funcţia isFinite() verifică dacă valoarea transmisă este un număr final, respectiv dacă valoarea
transmisă este diferită de NaN, Infinity şi -Infinity.
Dacă în acest moment nu vă este clar ce am menționat aici despre funcţii, aveţi răbdare, totul va
deveni clar când vom vorbi despre funcții într-o lecție specială. Pentru moment, este suficient să
reţineţi la ce se folosesc funcțiile isNaN() și isFinite(); despre modul lor de utilizare, vom vorbi
mai târziu.
Mai multe despre lucrul cu numere, veți afla în lecţia „Lucrul cu numere şi string-uri”.
String-uri
În limbajul JavaScript, string-urile servesc la stocarea literelor, a numerelor și a altor caractere
Unicode. Practic, string-urile se utilizează pentru a afișa textul. String-urile se plasează între
ghilimele simple sau duble:
1
2
var x = 'text 1';
var y = "text 2";<span style="font-size: 14px; text-align: justify;"> </span>
În acest exemplu, ambele variabile sunt de tip string.
27
Mai multe despre lucrul cu string-urile, veți afla în lecţia „Lucrul cu numere şi string-uri”.
Boolean – valori logice
Numerele și string-urile pot avea valori nenumărate. Spre deosebire de ele, valorile logice pot avea
doar două variante: true (adevărat) sau false (fals). Aceste valori sunt utilizate, de obicei, cu ocazia
unor structuri de control unde efectuăm o testare. Dacă testarea are succes, această afirmație este
adevărată, valoarea returnată va fi true, în caz contrar, valoarea va fi false.
Exemplu:
1
2
var x = 5 == 1;
document.write(x);<span style="font-size: 14px; text-align:
justify;"> </span>
Cu acest cod, am testat mai întâi afirmația că cele două numere sunt egale (== este operator logic
pentru compararea valorilor). Calculatorul a efectuat testarea și a constatat că declarația nu este
adevărată, motiv pentru care variabilei x i-a fost atribuită valoarea false. Cu a doua linie de cod,
vom scrie valoarea variabilei x pe pagină.
Această afirmație ar atribui variabilei x valoarea true:
1 var x = 5 == 5;
Valoarea specială null
null este o valoare specială, diferită de toate celelalte. Când această valoare este atribuită unei
variabile, putem considera că aceasta înseamnă că variabila nu conține nimic folositor (niciun
obiect, string, număr, text, valoare logică etc.). Dacă forțăm JavaScript să observe valoarea null în
contextul valorilor logice, aceasta va fi convertită în valoarea false.
Valoarea specială undefined
Ca şi null, şi undefined este o valoare primitivă specială în JavaScript. Această valoare se foloseşte
atunci când se încearcă accesarea valorilor unei variabile care este declarată, dar ei nu îi este
atribuită nicio valoare.
Exemplu:
28
1
2
var x;
document.write(x);
Noţiunea de şir în JavaScript
În cadrul acestei lecţii, ne vom familiariza și cu conceptul de şir în JavaScript. Şirurile sunt un alt
element esenţial din programare, fără de care cu greu ne putem imagina o funcţionalitate mai
serioasă. De fapt, şirurile sunt suporturi de date la fel ca şi variabilele, diferenţa constând în faptul
că au o structură complexă. Când spunem aceasta, de obicei ne referim la tipurile care, de fapt,
nici nu conţin o valoare, ci doar o anumită locaţie în memoria pe care se află valoarea respectivă,
în timp ce datele se extind pe memorie până la locaţia marcată şi mai departe.
Ce este, mai exact, un şir? Şirul este un set de date, unde fiecare se află pe o anumită poziţie
indexată.
De exemplu, dacă avem un set de numere 3,5,2,6,1,6, observăm că numărul 6 se repetă. Asta
înseamnă că, dacă am vrea să scoatem din listă numărul 6, nu am avea o informaţie precisă despre
care din cele două numere este vorba. Unul din modurile în care putem rezolva această problemă
este prin introducerea numerotării elementelor din acest set:
element 3 5 2 6 1 6
poziţie 0 1 2 3 4 5
Tabelul 4.2.
Acum este foarte simplu să identificăm orice număr în orice moment. Dacă am vrea să afişăm unul
din cele două numere 6, am putea să transmitem una dintre cele două poziţii (3 sau 5). Pe acelaşi
principiu funcţionează şi şirurile.
Există mai multe moduri de iniţializare a unui şir. Îl putem declara cu sau fără dimensiunea iniţială
(numărul de elemente):
1 var arr = new Array();
sau:
1 var arr = new Array(10);<span style="font-size: 14px; text-align: justify;"> </span>
29
Al doilea exemplu nu prea are sens, fiindcă, spre deosebire de limbajele de programare de nivel
inferior (c, c++), JavaScript nu trebuie să aibă determinată de dinainte dimensiunea şirului, fiindcă
acesta se mărește dinamic după necesitate. Totuşi, dacă am făcut şirul în acest fel (var arr = new
Array(10);), respectiv dacă între paranteze am transmis numărul, aceasta înseamnă că JavaScript
va crea noul şir al cărui identificator este cuvântul arr şi care va avea rezervate 10 locuri în şirul
care returnează valoarea undefined.
De asemenea, putem folosi şi o notaţie prescurtată pentru crearea şirului:
1 var arr = [];
Totodată, șirul se poate iniţializa şi cu valori deja introduse. De exemplu, dacă am vrea să
iniţializăm un şir care ar conţine setul de numere de la începutul lecţiei, am scrie următoarele:
1 var arr = [3,5,2,6,1,6];
Acum este momentul oportun să vă atragem atenţia asupra unui lucru foarte important referitor la
şiruri, respectiv la numerotarea elementelor acestuia. Numerotarea poziţiilor pe care se află
elementele în şir începe de la numărul 0:
element 3 5 2 6 1 6
poziţie 0 1 2 3 4 5
Tabelul 4.3.
Aceasta înseamnă că, în şir, pe poziţia 0 se află numărul 1, numărul 5 etc., fiindcă în şiruri se
foloseşte aşa-numita numerotare „Zero based”. Înseamnă că numerotarea indexului şirului începe
de la 0.
Pentru a accesa un element care se află în şir, este suficient să ştim despre care şir este vorba şi
care este poziţia elementului pe care îl căutăm.
De exemplu:
1 x=arr[3];
va atribui variabilei x valoarea din şir numerotată cu numărul 3. Respectiv, dacă manipulăm şirul
3,5,2,6,1,6, acesta va fi numărul 6 (al patrulea la rând din pricina structurii bazate pe 0).
La fel, am putea să punem şi o anumită valoare în şir:
30
1 arr[3]=5;<span style="font-size: 14px;"> </span>
Prin urmare, noi accesăm un element al şirului prin index, fiindcă fiecare element al şirului se află
pe o anumită poziţie determinată de index. Dacă vrem să scriem toate elementele şirului, putem
menţiona doar denumirea variabilei care conţine şirul respectiv:
1
2
3
4
var n=[];
n[0]=2;
n[1]=7;
document.write(n);
Rezultatul executării acestei instrucţiuni vor fi toate elementele pe care le conţine şirul, respectiv,
în exemplul nostru, pe ecran se va afișa 2,7. Dacă vrem să accesăm un element individual al şirului
sau un element al şirului determinat cu precizie, atunci trebuie să folosim indecşii prin care sunt
numerotate elementele şirului.
Să ne întoarcem acum la tipurile din şir. Şirul poate stoca diferite tipuri de date.
Exemplu:
1 var arr = [5, true, "text", [5,2]];
În cele mai frecvente cazuri deosebim două tipuri. Structura menţionată, cea care implică
numerotarea numerică a elementelor şirului, se numeşte şir numeric sau şir indexat, iar structura
în care fiecare element al şirului posedă o cheie care îl identifică se numeşte şir asociativ. Spre
deosebire de alte limbaje de programare, în JavaScript nu există un şir asociativ real, ci este vorba
despre obiect. Totuşi, acest fapt nu ar trebui să ne intereseze în mod special acum şi vom continua
să denumim aceste obiecte, şiruri asociative.
1
2
3
4
5
6
var arr = [];
arr['Serbia'] = "Belgrad";
arr['Franta'] = "Paris";
arr['Germania'] = "Berlin";
document.write(arr['Serbia']);<span style="font-size: 14px; text-align:
justify;"> </span>
Exemplul de mai sus reprezintă un şir asociativ, deoarece valorile sunt ascunse în spatele unor chei
(statele sunt chei, iar oraşele sunt valori). Într-un astfel de şir, la valoare se ajunge prin introducerea
cheii între parantezele pătrate ale variabilei, la fel ca în exemplu.
31
Până acum am stabilit cum să punem elementul în şir și cum să citim un element din şir. Dar aceste
proceduri nu sunt prea automate şi nu fac diferenţă între şiruri şi alte variabile. De aceea, adevărata
putere a şirurilor iese în evidenţă doar atunci când se manipulează prin diferite tipuri de bucle,
despre care vom discuta în lecțiile următoare.
Definirea tipurilor de date şi conversaţia
Ca și celelalte limbaje script, JavaScript are mecanisme de detectare automată a tipului introdus.
Acest lucru înseamnă că, odată cu inițializarea variabilei, nu trebuie să subliniem în mod explicit
ce tip vom manipula. De exemplu:
1
2
var x=1;
var x="1";<span style="font-size: 14px; text-align: justify;"> </span>
În ambele cazuri, interpretul va trata diferit variabila x. În primul caz, ca număr, în al doilea, ca
text. Acest lucru poate fi complet lipsit de sens, dacă variabilele ne sunt necesare doar pentru o
reprezentare de ieşire, dar dacă dorim să le manipulăm pentru a le prelucra ulterior, este nevoie de
o atenţie sporită.
De exemplu:
1
2
3
var x=1;
var y="2";
document.write(x+y);<span style="font-size: 14px; text-align:
justify;"> </span>
Exemplul va afișa pe pagină rezultatul 12. Interpretul JavaScript a recunoscut tipurile ambelor
variabile (deși nu le-am specificat nicăieri în mod explicit). x este recunoscut ca număr, iar y ca
String (text). Dar, atunci când se utilizează operatorul +, având în vedere că interpretul nu poate
aduna textul și numărul, el convertește numărul în text (pentru că aceasta este o conversie sigură,
în timp ce textul se poate converti în număr doar în cazul în care textul este compus din numere),
uneşte ambele variabile și emite o ieşire, rezultatul pe pagina fiind 12.
Rezultatul următorului exemplu:
1
2
3
var x=1;
var y=2;
document.write(x+y);
ar fi, desigur, 3.
32
Asta nu înseamnă că exemplul anterior nu poate fi adaptat pentru ca rezultatul să dea adunarea şi
nu concatenarea string-ului. Este nevoie doar ca undeva în codul String să convertim variabila într-
un număr cu funcția parseInt(). Funcția parseInt() se foloseşte plasând între paranteze obişnuite
valoarea care trebuie convertită în valoare întreagă:
1
2
3
4
var x=1;
var y
var y=parseInt("2");
document.write(x+y);
sau:
1
2
3
var x=1;
var y="2";
document.write(x+parseInt(y));<span style="font-size: 14px; text-align:
justify;"> </span>
În ambele cazuri, rezultatul va fi 3.
Dacă am dori să convertim numărul într-o valoare zecimală în loc de una întreagă, am folosi funcţia
parseFloat() în loc de funcţia parseInt().
În JavaScript tipul de număr întreg, practic, nu are limite. Respectiv, limitarea este apropiată de +-
9,000,000,000,000,000 (53 de biţi).
Trebuie să menţionăm faptul că, atunci când lucrăm cu numere atât de mari, nu ar trebui să folosim
valori numerice, ci string-uri.
Folosind operatorul + peste string-uri, se ajunge la concatenarea string-urilor:
1
2
3
var x="Thomas";
var y="Miller";
document.write(x+y);<span style="font-size: 14px;"> </span>
Rezultatul este „ThomasMiller”.
În timp ce pentru cod:
1 var x="1";
var y="2";
33
2
3
document.write(x+y);<span style="font-size: 14px; text-align:
justify;"> </span>
rezultatul este 12. Am avut ocazia să ne convingem de asta şi în lucrul cu numerele.
De aici, vedem că în JavaScript lucrul cu string-uri este destul de simplu, trebuie doar să acordăm
atenție câtorva detalii.
În primul rând, în JavaScript (și în toate celelalte limbaje) string-ul este, de fapt, o listă
(înșiruire/şir) de caractere. Uneori, în string trebuie să introducem niște simboluri speciale
(diacritice) cu care îi vom indica calculatorului activitatea pe care trebuie să o întreprindă în acel
loc. Pe de altă parte, uneori vom dori ca în string să existe diacritice, dar JavaScript să continue
să-l interpreteze ca orice literă sau număr. Atunci, cu ajutorul caracterului Escape (\), specificăm
că următorul caracter nu ar trebui interpretat separat, ci doar afișat.
Deci, dacă am dori ca script-ul nostru să aibă următoarea ieşire:
1 "test"<span style="font-size: 14px;"> </span>
ar trebui să iniţializăm String-ul care în conţinut va trata special ghilimele cu caractere escape:
1
2
var x="\"test\"";
document.write(x);<span style="font-size: 14px; text-align:
justify;"> </span>
Acest cod va da rezultatul dorit la ieşire, în timp ce codul:
1
2
var x=""test"";
document.write(x);<span style="font-size: 14px;"> </span>
va raporta o eroare.
În ceea ce privește ghilimelele, în JavaScript mai există un truc care poate fi utilizat. Când
inițializăm string-ul, putem plasa textul dorit şi între ghilimele simple, în locul ghilimelelor duble.
Astfel, am putea pune ghilimele duble în conținutul acelui string, fără a cauza o eroare:
1
2
var x='"test"';
document.write(x);<span style="font-size: 14px; text-align:
justify;"> </span>
Acest cod va emite un rezultat valid şi nu va duce la eroare.
34
Puteţi verifica tipul variabilei cu funcţia typeof().
Exemplu:
1
2
var x=10;
document.write(typeof(x));<span style="font-size: 14px;"> </span>
va afișa ca rezultat number.
Mai multe despre conversia tipurilor de date
Am menţionat deja câteva exemple de convertire a string-ului în număr cu ajutorul funcției
parseInt() și parseFloat() și am menţionat conversia automată (conversia implicită) la care recurge
JavaScript în unele cazuri. Deoarece JavaScript este un limbaj aşa-numit dinamically typed, nu
suntem obligați să menționăm în mod explicit despre ce tip de date este vorba atunci când se face
declarația, lucru obligatoriu în alte limbaje. În loc, JavaScript convertește automat tipul de date în
funcție de nevoile actuale.
Să analizăm cu atenţie următorul exemplu:
1
2
3
4
var number = 56;
var text = "The answer is";
var text_number = text + number;
document.write(text_number);
În primul rând, am declarat variabila number căreia i-am atribuit valoarea 56. JavaScript a atribuit
automat acestei variabile tipul Number. După aceea, am declarat şi variabila text căreia i-am
atribuit valoarea "The answer is" și de aceea JavaScript i-a atribuit acestei variabile tipul String.
Totuşi, după aceea, cu ajutorul operatorului + am efectuat unirea celor două variabile. JavaScript
va converti automat tipul. Cum textul nu se poate converti în siguranță în număr, în loc de adunare,
JavaScript efectuează concatenarea, respectiv concatenarea string-urilor prin reconvertirea
numărului anterior în string "56". De aceea, ca rezultat al ultimei linii de cod, la ieşire vom obține
înscrisul:
1 The answer is 56
Ar trebui să avem în vedere faptul că rezultatul acestei concatenări este plasat în variabila
text_number, care este de tip String.
Să analizăm acum în detaliu utilizarea operatorului unar plus (+) în următorul exemplu:
35
1 "1.1" + "1.1"<span style="font-size: 14px; text-align: justify;"> </span>
În acest caz, rezultatul "1.11.1" este cel așteptat, deoarece am concatenat două string-uri. Totuşi,
conversia literalilor se poate face în aşa fel încât în fața literalului să introducem operatorul unar +
ca în exemplul următor:
1 (+"1.1") + (+"1.1")<span style="font-size: 14px; text-align:
justify;"> </span>
În acest caz, rezultatul adunării va fi 2.2, deoarece string-urile au fost convertite înainte în numere.
De asemenea, parantezele se află aici din motive de claritate, așa că şi următorul cod va da acelaşi
rezultat:
1 +"1.1" + +"1.1"
Constantele
În afara variabilelor, multe limbaje de programare mai recunosc încă un tip de valori definite de
utilizator, a căror valoare, după inițializare, este fixă. Acest tip se numește constantă. În
JavaScript, constanta nu există, iar limitările accesului la variabile se realizează doar pe baza
intervalului ei de vizibilitate. În momentul în care a fost scris acest text, JavaScript nu avea
capacitatea de a crea constante reale, iar valorile variabilelor puteau fi protejate de modificări prin
plasarea în funcții, despre care vom discuta în lecțiile următoare. Pe lângă aceasta, exista, la nivel
experimental, și tehnologia const. Proiectul ECMAScript pentru versiunea 6 aduce tehnologia
experimentală const, cu care se poate defini constanta. Momentan, const funcţionează în Firefox
şi se așteaptă să fie implementat în curând şi în alte browser-e moderne.
Sintaxa este următoarea:
1 const PI = 3.14;<span style="font-size: 14px; text-align: justify;"> </span>
Această variabilă nu se poate schimba mai târziu. De exemplu:
1
2
3
const PI = 3.14;
PI = "text";
document.write(PI);<span style="font-size: 14px;"> </span>
Ieşirea pe pagină ar fi în continuare 3.14, iar JavaScript ar defini avertizarea pentru linia 2.
36
Operatorii
Unitate: 5 din 19 00:09:56
+Rezumat
Pe lângă variabile şi literali, în JavaScript vom mai folosi în mod constant şi diferiţi operatori.
JavaScript distinge un număr mare de operatori pe care îi putem clasifica în felul următor:
Operatori de atribuire;
Operatori aritmetici;
Operatori de comparaţie;
Operatori logici;
Operatori Bitwise;
Operatori String;
Operatori speciali.
Operatorii de atribuire
Implică atribuirea valorii unei anumite variabile:
1
2
3
var a=10;
var x=5;
var z=3;<span style="font-size: 14px; text-align: justify;"> </span>
Este clar că operatorul de bază al atribuirii este semnul =.
Totuşi, există şi anumite combinaţii de semne care pot avea, de asemenea, posibilitatea de atribuire,
însă despre ele spunem că sunt mai degrabă abrevieri decât operatori. De exemplu, vrem să mărim
o variabilă cu 5 - putem scrie acest lucru aşa:
1 x = x + 5;
Dar, putem obține acelaşi efect şi dacă scriem versiunea prescurtată a acestui cod:
1 x += 5;<span style="font-size: 14px; text-align: justify;"> </span>
Aici, avem tabelul cu operatorii de atribuire folosiţi cel mai des.
Să presupunem că x are valoarea 10 şi y valoarea 3:
37
Prezentarea utilizării operatorului Semnificaţie Valoarea lui x după atribuire
x -= y x = x - y 7
x *= y x = x * y 30
x /= y x = x / y 3.3333333333333335
x %= y x = x % y 1
Tabelul 5.1.
Operatorii aritmetici
Fiecare operaţie aritmetică necesită şi un operator aritmetic (+, -, *, /, %). Semnele de adunare şi
scădere sunt clare, în timp ce ceilalţi trei operatori sunt: * pentru înmulţire, / pentru împărţire şi %
pentru rest. Operatorii aritmetici manipulează tipurile numerice de date şi ca rezultat returnează o
valoare numerică.
Operator Descriere
+ adunare
- scădere
* înmulţire
/ împărţire
% rest
++ increment
-- decrement
Tabelul 5.2. Tabelul operaţiilor aritmetice
Primii patru operatori din tabel sunt clari, deoarece sunt folosiţi pentru operațiile matematice de
bază. Operatorul aritmetic Modulus (%) este folosit pentru a calcula restul întreg după împărţire.
Exemplu:
1
2
3
4
var x = 11;
var y = 3;
var z = x % y;
document.write(z);<span style="font-size: 14px; text-align:
justify;"> </span>
38
După împărţirea numărului 11 cu numărul 3, vom obține rezultatul 9 cu rest 2. Deoarece acest
operator returnează doar restul ca valoare întreagă, rezultatul este 2.
Operatorii ++ şi - aplică increment (creșterea cu 1) sau decrement (micşorarea cu 1) variabilei pe
care se află.
Exemplu:
1
2
var x = 3;
y = ++x;<span style="font-size: 14px; text-align: justify;"> </span>
După efectuarea acestui cod, valoarea variabilei x şi valoarea variabilei y va fi 4.
Dacă semnul aritmetic pentru increment ar fi stat în partea dreaptă a variabilei ca în exemplul
următor:
1
2
var x = 3;
y = x++;<span style="font-size: 14px; text-align: justify;"> </span>
variabila x ar fi avut valoarea 4, dar variabilei y i-ar fi fost atribuită valoarea 3, căci mai întâi s-ar
fi efectuat atribuirea valorii variabilei y şi abia apoi s-ar fi aplicat increment variabilei x.
În timpul executării operaţiilor aritmetice, trebuie să avem grijă la ordinea executării acestora. În
JavaScript, operaţiile matematice se execută în aceeaşi ordine ca în matematică. Înmulţirea şi
împărţirea au prioritate faţă de adunare şi scădere. Ordinea executării operaţiilor se poate schimba
prin utilizarea parantezelor.
Operatorii de comparaţie
Operatorii de comparaţie execută compararea anumitor operanzi şi ca rezultat dau o valoare logică
(true sau false):
1 operand1 operator_comparaţie operand2<em style="text-align: justify;"> </em>
Îi folosim atunci când vrem să determinăm în ce raport se află două valori.
Operator Descriere Exemplu Valoare pentru
exemplu
== Compară dacă două valori sunt la fel. 8 == 8
"8" == 8
true
true
39
=== Compară dacă două valori sunt identice. 8 === 8
"8"===8
true
false
!= Verifică dacă valorile nu sunt la fel. 8 != 5
8 != 8
true
false
!== Verifică dacă valorile nu sunt identice. 8 !== 8
"8"!== 8
false
true
> Verifică dacă valoarea din partea stângă este mai
mare decât valoarea din partea dreaptă.
8 > 5
8 > 10
true
false
< Verifică dacă valoarea din partea stângă este
mai mică decât valoarea din partea dreaptă.
8 < 5
8 < 10
false
true
>= Verifică dacă valoarea din partea stângă este mai
mare sau egală cu valoarea din partea dreaptă.
8 >= 5
8 >= 8
8>=10
true
true
false
<= Verifică dacă valoarea din partea stângă este
mai mică sau egală cu valoarea din partea dreaptă.
8 <= 5
8 <= 8
8 <= 10
false
true
true
Tabelul 5.3. Tabelul operatorilor de comparare
Operatorii == şi === sunt puţin mai greu de înțeles în acest moment, aşadar ar fi bine să îi explicăm
suplimentar printr-un exemplu practic.
Să luăm următorul bloc:
1
2
3
var x = 5;
var y = "5";
var z = x ===y;
Valoarea variabilei z va fi false, deoarece, deşi valorile variabilelor x și y sunt egale, tipurile sunt
diferite, iar acest operator atribuie valoarea true numai atunci când avem două date comparate cu
aceleași valori, dar şi același tip. Astfel, în cazul următor valoarea variabilei z va fi true, deoarece
valoarea și tipul variabilelor x și y sunt egale:
40
1
2
3
var x = 5;
var y = 5;
var z = x ===y;<span style="font-size: 14px; text-align: justify;"> </span>
Valoarea variabilei z va fi true, deoarece variabilele x şi y au acelaşi tip (Number) şi
aceleaşi valori (5).
Operatorii logici
Aceşti operatori se folosesc pentru operaţii algebrice logice. Cel mai des, îi putem vedea în
combinaţie cu operatorii de comparaţie, unde se folosesc cu scopul de a efectua comparaţii mai
complexe cu mai multe variabile. Ca rezultat, operatorii logici returnează valori de tip boolean.
Conjuncţia logică (&&)
Operatorul && (logic AND) efectuează o conjuncție logică a doi operanzi. Aceasta înseamnă că
valoarea returnată va fi true dacă şi doar dacă ambii operanzi au valoarea true. Totuşi, trebuie să
menţionăm că este suficient ca doar un singur operand să aibă valoarea false pentru ca rezultatul
să fie false.
Exemple:
1
2
3
4
var a1 = true && true; //variabila a1 primeşte valoarea true
var a2 = true && false; //variabila a2 primeşte valoarea false
var a3 = false && true; //variabila a3 primeşte valoarea false
var a4 = false && false; //variabila a4 primeşte valoarea false<span style="font-size: 14px; text-align: justify;"> </span>
În loc de valorile logice, putem folosi şi expresii:
1 var a1 = (3 > 0) && (3 < 5); // variabila a1 primeşte valoarea true
Disjuncţia logică (||)
Operatorul || (logic OR) efectuează disjuncția logică a doi operanzi. Ca şi operatorul anterior (&&),
și || este un operator binar, ceea ce înseamnă că manipulează cu doi operanzi. Returnează valoarea
logică true dacă măcar unul dintre operanzi este true:
1 var o1 = true || true; // variabila o1 primeşte valoarea true
41
2
3
4
var o2 = false || true; // variabila o2 primeşte valoarea true
var o3 = true || false; // variabila o3 primeşte valoare true
var o4 = false || false; // variabila o4 primeşte valaorea false
Negaţia logică (!)
Spre deosebire de ultimele două, acest operator nu este binar, ci unar. Deci, pentru operațiunile
sale nu foloseşte doi, ci doar un operand. Operandul poate fi o valoare logică sau o expresie. Scopul
acestui operator este inversul operandului logic cu care se află.
Exemplu:
1
2
var n1 = !true; // Variabila n1 primeşte valoarea false
var n2 = !false; // Variabila n2 primeşte valoarea true
Pentru cei care vor să afle mai multe
Dacă operatorul ! se află lângă operandul care nu reprezintă o valoare logică, el va fi mai întâi
convertit la o valoare logică corespunzătoare, iar apoi se va efectua negaţia acestei valori. Acest
lucru ne indică faptul că putem converti o valoare lipsită de logică într-una logică, efectuând asupra
ei o dublă negare (!!x).
Utilizarea numerelor și a string-urilor
Unitate: 6 din 19 00:16:48
+Rezumat
În cadrul acestei lecţii, ne vom familiariza în detaliu cu numerele şi cu string-urile, precum şi cu
modul în care JavaScript le interpretează. De asemenea, vom vedea cum putem manipula numerele
cu ajutorul funcţiilor Math ale obiectului.
Lucrul cu numere
Unul dintre cele mai interesante tipuri de date pe care JavaScript îl susține sunt, desigur, numerele.
Spre deosebire de celelalte limbaje de programare familiare, JavaScript nu face diferenţa între
valorile integer şi float, aşadar, de exemplu, numărul 2 şi 2.0 reprezintă acelaşi tip de valori. În
JavaScript, toate numerele sunt reprezentate prin valoarea float. JavaScript foloseşte reprezentările
42
numerelor pe 64 de biţi, definite de standardul IEEE 754. Acest standard stabilește că se pot afișa
toate numerele până la 1.7976931348623157 X 10308. Formatul de numere JavaScript permite
unui programator să afișeze toate valorile integer cuprinse între −9007199254740992 (−253) şi
9007199254740992 (253), inclusiv şi aceste numere. Dacă folosiţi valori integer mai mari decât
acestea, puteţi pierde din precizia cifrelor.
În limbajul JavaScript, valoarea base - 10 integer se scrie ca un şir de cifre. Valorile base - 10
reprezintă numerele sistemului zecimal (alcătuit din numere ale căror cifre sunt valori între 0 şi 9).
De exemplu:
1
2
3
0
8
2135435<span style="font-size: 14px; text-align: justify;"> </span>
În afară de literalul base - 10 integer, JavaScript recunoaşte, de asemenea, şi valorile hexazecimale
base - 16. Literalii hexazecimali încep cu marcajul "0X", care este urmat de string-ul scrierii
hexazecimale. Scrierea hexazecimală este reprezentată prin numere de la 0 la 9 şi cu litere începând
de la A până la F, care reprezintă valorile de la 10 până la 15. Iată câteva exemple de literali
hexazecimali:
1 0xff // 15*16 + 15 = 255<span style="font-size: 14px; text-align:
justify;"> </span>
Unele implementări ale lui JavaScript suportă numere în format octal. Octalii încep cu 0, după care
se află anumite numere în intervalul cuprins între 0 şi 7. De exemplu:
1 0056 // 5*8 +6=46<span style="font-size: 14px; text-align: justify;"> </span>
Totuşi, nu toate implementările lui JavaScript susţin lucrul cu literalii octali, aşadar niciodată nu
trebuie scrisă o valoare integer cu zero la început, deoarece nu puteţi şti despre ce implementare
JavaScript este vorba. Dacă nu are suport pentru lucrul cu valorile octale, JavaScript va considera
acest număr ca valoare base - 10. Aceasta înseamnă că numărul va fi afișat ca un simplu număr al
sistemului zecimal cu care suntem obişnuiţi, aşadar nu poate începe cu zero.
La fel ca toate obiectele din JavaScript, şi numerele au metodele lor pentru manipularea uşoară a
valorilor.
În JavaScript, numerele au metode speciale pentru lucrul cu valorile numerice. JavaScript are
încorporat obiectul Math, cu ajutorul căruia se pot executa multe funcţionalităţi asupra valorilor
numerice. În continuarea lecţiei, vom avea oportunitatea să vedem cum putem folosi funcţiile Math
pentru lucrul cu numere. Despre funcţii vom discuta într-una dintre lecţiile viitoare, așa că urmează
ca aici să ne familiarizăm pe scurt cu bazele funcţiilor în JavaScript. Prin urmare, funcţiile
reprezintă un segment separat al codului, care funcţionează ca un întreg şi care are propria sa
43
denumire. Pentru a executa funcţia, trebuie să o apelăm. Fiindcă acum vom lucra cu
funcţiile deja definite ale obiectului Math, trebuie doar să le apelăm.
Există multe operaţii matematice care se pot aplica asupra diferitor valori de numere, iar aceste
operaţii sunt definite prin funcţii. De exemplu:
1
2
var y=Math.round(5.4);
document.write(y);<span style="font-size: 14px; text-align:
justify;"> </span>
Folosim funcţia round() pentru a rotunji un număr. Principiul de rotunjire este acelaşi cu cel pe
care îl întâlnim de obicei, aşadar numărul 5,4 va fi rotunjit la 5, iar numărul 5,5 va fi rotunjit la
valoarea 6. În exemplu, am introdus variabila y care salvează valoarea returnată a funcţiei round(),
apoi scriem noua valoare pe pagină cu ajutorul obiectului document şi al metodei sale write(). Știți
deja că funcțiile necesită transmiterea unei anumite valori între parantezele obişnuite. Denumim
această valoare parametru. Pentru moment, este suficient să știţi că anumite funcții operează fără
parametri, altele au nevoie să li se transmită un parametru, iar altele au nevoie de mai mulţi
parametri. Dacă transmitem funcției mai mulți parametri, îi separăm prin virgule.
Deşi cel mai des vom utiliza funcţia round(), pentru că servește la rotunjirea matematică clasică,
trebuie să menționăm și funcțiile ceil() şi floor(), care funcţionează la fel. Utilizarea funcțiilor este
aceeași; totuşi, funcția ceil() va rotunji numărul la prima valoare întreagă mai mare, în timp ce
funcția floor() va returna prima valoare întreagă mai mică. Desigur, acest comportament al funcției
se manifestă atunci când i se atribuie o valoare zecimală; dacă tuturor funcțiilor li se atribuie un
număr întreg, funcţiile nu vor executa nicio modificare, ci vor returna numărul care le-a fost
atribuit.
Exemplu pentru ceil():
1
2
var x = Math.ceil(10.3);
document.write(x);<span style="font-size: 14px; text-align:
justify;"> </span>
După prima linie de cod, variabila x va avea valoarea 11.
Exemplu pentru floor():
1
2
var x = Math.floor(10.3);
document.write(x);<span style="font-size: 14px; text-align:
justify;"> </span>
După prima linie de cod, variabila x va avea valoarea 10.
44
În exemplul următor, vedem cum să obţinem valoarea absolută a unui anumit număr. Pentru a nu
pierde timp elaborând un algoritm adecvat, JavaScript, la fel ca multe alte limbaje de programare,
oferă o soluţie eficientă, şi anume funcţia Math abs():
1
2
var x=Math.abs(-3);
document.write(x);<span style="font-size: 14px; text-align:
justify;"> </span>
După executarea primei linii de cod, variabila x va primi valoarea 3.
Această metodă funcţionează pe baza principiului valorii absolute, aşadar fiecare număr negativ
este transformat într-unul pozitiv, în timp ce numărul pozitiv lasă acelaşi semn. Este similar
exemplului precedent, în care rezultatul executării funcţiei se salvează într-o anumită variabilă,
pentru ca valoarea să fie scrisă pe pagină şi pentru a-i verifica rezultatul după executarea funcţiei.
Următoarea operație, foarte utilă în ceea ce privește numerele, este, desigur, ridicarea la putere.
Deşi ridicarea la putere cu un exponent mai mic se poate rezolva într-un alt mod, printr-o simplă
înmulţire, această abordare nu este în niciun caz convenabilă pentru ridicarea la putere cu exponent
mare. Spre deosebire de funcţiile precedente, aici ne întâlnim cu funcţia căreia trebuie să-i
transmitem doi parametri. Primul parametru este baza numărului, iar al doilea parametru este
exponentul la care trebuie ridicat numărul respectiv. Funcţia care execută această operaţie se
numeşte pow(), prescurtarea de la power, cuvântul din limba engleză pentru putere:
1
2
var x=Math.pow(-3,2);
document.write(x);<span style="font-size: 14px; text-align:
justify;"> </span>
În acest exemplu, i-am indicat funcţiei să execute următoarea operaţie matematică: (-3,2). După
executarea funcţiei şi după scrierea valorii acesteia pe pagină, putem vedea că rezultatul este, într-
adevăr, 9.
Am fi obținut acelaşi rezultat şi prin simpla înmulţire a numerelor:
1
2
var x=-3*-3
document.write(x);
Această operaţie este analoagă ridicării numărului la pătrat, aşadar obţinem acelaşi rezultat. Însă,
imaginaţi-vă că vreţi să efectuați (5,43). Ar fi trebuit să înmulţiţi numărul 5 de 43 de ori. De aceea,
pentru puteri mari se recomandă utilizarea funcţiei pow().
Este important să știți că uneori veți primi parametrii pentru această funcție dinamic, ceea ce
înseamnă că nu veţi ști singuri la ce grad ar trebui să ridicaţi numărul. Să presupunem că aţi făcut
o aplicație care ridică numărul la gradul pe care utilizatorul l-a introdus în forma input.
45
Următoarea funcţie foarte importantă, pe care o veţi folosi deseori în timpul lucrului, este
random(). Aceasta este, de fapt, funcţia pentru obţinerea unui număr aleatoriu. De fiecare dată
când reîncărcaţi pagina, veţi obţine o nouă valoare ca rezultat al executării funcţiei:
1
2
var x=Math.random();
document.write(x);
În exemplu, am apelat pur şi simplu funcţia random() prin obiectul Math, iar după cum vedem, nu
a trebuit să-i transmitem niciun parametru. Această funcţie va returna de fiecare dată un alt rezultat.
Intervalul rezultatelor posibile ale acestei funcţii variază de la numărul 0 (inclusiv zero) până la
numărul 1.
De asemenea, o funcţie Math foarte utilă este şi max(). După cum v-aţi dat probabil seama,
rezultatul executării funcţiei foarte intuitive este numărul care are valoarea cea mai mare. Funcţia
primeşte un număr arbitrar de parametri, apoi, dintre parametrii transmişi, îl returnează pe cel cu
valoarea cea mai mare:
1
2
var x=Math.max(5,2,8);
document.write(x);
În exemplu, funcţiei max() i-am transmis 3 parametri cu valorile 5, 2 şi 8. După cum putem
concluziona, funcţia va returna numărul 8, deoarece acesta este cel mai mare număr dintre cele
rămase pe care le-am transmis funcţiei max().
Ultima funcţie a obiectului Math, pe care o vom analiza în cadrul acestei lecţii, este sqrt(). Aceasta
este funcţia care execută operaţia de extragere a rădăcinii pătrate:
1
2
var x=Math.sqrt(2);
document.write(x);
În acest exemplu, am apelat funcţia Math a obiectului sqrt(), căreia îi transmitem numărul a cărui
rădăcină vrem să o extragem. Rezultatul executării funcţiei se salvează în variabila x, a cărei
valoare o scriem pe ecran. Într-un exemplu concret, vom obţine rezultatul operaţiei de extragere a
rădăcinii din 2, respectiv 1.41.
Lucrul cu string-uri
String-ul este tipul de dată care conţine un şir de valori pe 16 biţi, în care fiecare valoare reprezintă
un caracter Unicode. String-urile se folosesc pentru a salva valorile textuale. Lungimea string-ului
se poate exprima şi prin numere. În JavaScript, string-urile folosesc numerotarea Zero based, ceea
ce înseamnă că valoarea de pe prima poziţie va avea indexul 0. Un string gol are lungimea 0.
JavaScript nu are un tip special de date prin care să reprezinte un element individual al string-ului,
după cum este cazul în celelalte limbaje de programare, unde există tipul special char. JavaScript
46
foloseşte un set de caractere UTF - 16, pentru a reprezenta valorile textuale.
Așa cum am menționat pe scurt în lecția despre tipurile de variabile, atunci când vrem să definim
un caracter special, putem face acest lucru în felul următor:
1
2
varvar1='Text: "This is a sample text"';
document.write(var1);<span style="font-size: 14px; text-align:
justify;"> </span>
În acest mod, putem să scriem textul dorit cu ajutorul ghilimelelor. Astfel, rezultatul executării
exemplului va fi: Text: "This is a sample text".
Există numeroase funcţii care se pot aplica în lucrul cu string-uri. Să luăm exemplul următor:
1
2
3
var var1='Text: "This is a sample text"';
var i=var1.charAt(7);
document.write(i);
După cum am avut posibilitatea să vedem, în JavaScript o valoare textuală se afișează cu ajutorul
string-urilor. Cu ajutorul funcţiei charAt(), pe care am folosit-o în acest exemplu, putem accesa un
element individual al şirului de valori definit, care reprezintă o scriere textuală. Prin urmare,
această metodă returnează valoarea care reprezintă un caracter al reprezentării textuale date. După
cum puteţi vedea în exemplu, funcţiei i-am transmis numărul 7. Acest număr reprezintă indexul
şirului, respectiv poziţia pe care se află un anumit caracter. Când am transmis numărul 7, înseamnă
că funcţia ne returnează caracterul "T", fiindcă numerotarea şirului începe de la 0. Deci, caracterul
pe poziţia 0 este T, pe poziţia 1 este e, pe poziţia 2 este x şi aşa mai departe
În lecţiile precedente, am văzut cum putem uni valorile anumitor string-uri, folosind operatorul +.
Acum, vom vedea că există şi o funcţie a obiectului String care face acelaşi lucru. Funcţia de care
avem nevoie în acest scop se numeşte concat():
1
2
3
var var1="This is a" ;
varvar2=var1.concat("sample text.");
document.write(var2);
Ca rezultat al executării acestei metode, obţinem un string: This is a sample text. Cu ajutorul acestui
string, am apelat al doilea string şi am transmis textul pe care vrem să-l alăturăm primului string.
Rezultatul executării metodei concat() se salvează într-o variabilă separată care poate avea o
denumire arbitrară. În exemplu, am denumit-o var2. După executarea acestei funcţii, scriem
valoarea pe pagină.
47
De asemenea, o altă funcţie foarte importantă pentru manipularea string-urilor este substr(). Cu
ajutorul acestei funcţii, putem tăia string-ul, respectiv putem extrage o parte din el. De exemplu:
1
2
3
var var1="This is a sample text." ;
var sub=var1.substr(10,4);
document.write(sub);
Ca rezultat al executării acestei metode, obţinem string-ul samp. Metoda substr() efectuează
extragerea unei părţi din string, începând cu caracterul a cărui poziție este transmisă primei valori
numerice și returnează atâtea caractere câte sunt indicate în a doua valoare numerică transmisă
funcției. Deoarece indecșii se numără începând cu zero, caracterul cu indexul 10 este "s".
În următorul exemplu, vom vedea cum putem transforma toate minusculele în majuscule. Efectul
pe care îl obţinem prin utilizarea acestei funcţii este analog celui obţinut prin activarea opţiunii
Caps Lock de pe tastatură:
1
2
3
var var1="This is a sample text." ;
var var2=var1.toUpperCase();
document.write(var2);<span style="font-size: 14px; text-align:
justify;"> </span>
Mai întâi, am definit un string simplu şi l-am atribuit variabilei var1, apoi am definit variabila
var2, care primeşte valoarea pe care funcţia toUpperCase() o returnează atunci când îi transmitem
ca parametru prima variabilă var1. Rezultatul executării instrucţiunii din acest exemplu este: THIS
IS A SAMPLE TEXT.
Într-un mod foarte asemănător funcţionează și funcția toLowerCase() care transformă toate
majusculele în minuscule.
Mai târziu, vom vedea cât de utilă poate fi numărarea caracterelor într-un string. Pentru moment,
este important să prezentăm proprietatea pe care o putem folosi pentru a ajunge la această dată.
Exemplu:
1
2
3
var var1="This is a sample text." ;
var l=var1.length;
document.write(l);<span style="font-size: 14px; text-align:
justify;"> </span>
După acest bloc de cod, va fi definită variabila l, care este un tip numeric și are valoarea 22.
La final, menționăm încă o funcție foarte utilă care se aplică pe string-uri, la care vom reveni mai
48
târziu de mai multe ori, și anume funcția trim(). Cu ajutorul acestei funcții, eliminăm spațiile de la
începutul și sfârșitul string-ului.
Exemplu:
1
2
3
var var1=" Hello " ;
var var2= var1.trim();
document.write(var2);<span style="font-size: 14px; text-align:
justify;"> </span>
După executarea acestui cod, variabilei var2 îi este atribuită valoarea string-ului variabilei var1,
dar fără spaţiile din partea stângă şi dreaptă ale textului “Hello”.
Executarea condiţionată
Unitate: 7 din 19 00:25:25
+Rezumat
În această lecţie, vom învăţa cum putem aplica comenzile de ramificare în JavaScript. Aceste
comenzi sunt primele semne care ne transmit că un program este într-adevăr un program. Fără ele,
un program nu poate să facă prea multe, în afară de executarea unor comenzi şi operaţiuni simple
şi, eventual, de afişarea informațiilor pe ecran.
Pentru a introduce în program mai multe neliniarităţi şi controale, trebuie să hotărâm când şi ce
părţi din program să executăm. Primul şi principalul mod de a realiza acest lucru este prin utilizarea
comenzilor de ramificare, respectiv de executare condiţionată a programului.
Ramificarea condiţionată – if
Prima şi principala comandă de ramificare este comanda if. Aceasta este cunoscută practic în toate
limbajele şi reprezintă exact ceea ce înseamnă: „dacă”.
După cum cuvântul „dacă” de sine stătător nu are prea multă logică în retorică, tot aşa nu are logică
nici în programare, deoarece trebuie ca lângă el să punem o condiţie de care va depinde rezultatul
comenzii.
49
Imaginea 7.1.
După cum se poate vedea în schema de mai sus, programul se execută până când ajunge la partea
care provoacă ramificare (if), unde mai întâi se verifică condiţia. În cazul în care condiția este
îndeplinită (true), se execută codul definit (codul if). Dacă condiția nu este îndeplinită (false), se
sare peste if code (nu se execută) și se continuă cu încărcarea paginii.
Să ne imaginăm următorul scenariu: Trebuie să stabilim dacă variabila speed este mai mică de 10.
Dacă este, trebuie scris mesajul „Too slow...”.
Această condiţie trebuie să fie plasată între paranteze rotunde, imediat după cuvântul-cheie if, iar
rezultatul ei trebuie neapărat să fie de tip boolean:
1
2
3
if(aici definim condiţia){ aici definim mesajul }<span style="font-size: 14px; text-align: justify;"> </span>
Să vedem cum arată în cod:
1
2
3
4
var speed = 9; if (speed < 10) { document.write("Too slow..."); }
50
În acest exemplu, când se ajunge la verificarea condiţiei, dacă aceasta este îndeplinită sau nu (iar
aici condiţia este îndeplinită, deoarece valoarea expresiei este true), programul va activa linia de
cod care urmează după condiţie. Încercaţi să modificaţi valoarea variabilei speed la 10. Acum,
condiţia nu va fi îndeplinită, deoarece 10 nu este mai mic decât 10 (10 < 10), iar mesajul nu va fi
scris.
Blocul poate fi infinit, practic ar trebui să fim atenţi doar la un singur lucru, şi anume la faptul că
această „bucată” de cod poate să nu fie executată deloc. De aceea, trebuie să creăm o logică
completă a programului astfel încât, în niciun moment, executarea în sine să nu depindă de
condiţie, iar condiţia trebuie să afecteze doar tipurile de executare. De exemplu, nu trebuie să
declarăm o anumită variabilă în blocul condiţional, dacă de această variabilă avem nevoie mai
târziu în afara blocului condiţional. Acest lucru cauzează erori în multe limbaje. Limbajele de
scripting sunt imune la afişarea erorii în aceste cazuri, dar aceasta nu înseamnă că este o practică
bună să efectuăm codarea în acest mod.
Însăşi expresia condiţională poate avea o mărime nelimitată, până când din ea se poate extrage un
singur rezultat de tip boolean. Aşadar, ((a==5) && (b==10)) || ((x!=25) && (c===d)) va produce
un rezultat unic de tip boolean şi, ca atare, face ca expresia să fie valabilă în condiţie.
Dar dacă am dori să facem ceva special când condiţia nu se îndeplineşte?
Desigur, am putea seta următoarea condiţie în care vom executa o altfel de verificare:
1
2
3
4
5
6
7
var speed = 11; if (speed < 10) { document.write("Too slow..."); } if (speed >= 10) { document.write("Too fast!"); }
În acest exemplu, într-o anumită măsură, am putea rezolva problema în acest mod. Totuşi, în acest
cod există câteva deficienţe. În primul rând, în cazul în care prima condiţie este îndeplinită, cu
siguranță a doua condiţie nu va fi. Dar programul efectuează a doua testare. Putem spune că a doua
testare nu este foarte importantă pentru un cod atât de simplu, dar, dacă codul nostru ar fi mai
complex, şi testările ar fi mai numeroase, acest lucru ar deveni o problemă semnificativă. În final,
există o sintaxă specială, cu care îi transmitem programului: „Fă ceva dacă condiția este
îndeplinită, iar în cazul în care condiția nu este îndeplinită, fă altceva.”
Reprezentarea grafică a acestei structuri de cod ar putea fi prezentată în felul următor:
51
Imaginea 7.2.
Deci, dacă condiţia este îndeplinită (true), se va executa blocul if al codului (if code) şi se va sări
peste blocul alternativ (else code). Pe de altă parte, dacă condiţia nu este îndeplinită (false), se
trece imediat la blocul alternativ de cod (else code), așa că blocul de cod if (if code) va fi sărit.
Iată sintaxa acestei scheme:
1
2
3
4
5
6
7
8
9
if (<em>condiţia care se testează</em>) { <em>blocul de cod care va fi executat dacă este îndeplinită condiţia </em> }else{
<em>blocul de cod</em> <em>alternativ </em> }
După cum vedeţi, după închiderea blocului de cod if (paranteza acoladă închisă } ) postăm
cuvântul-cheie else, după care definim blocul de cod alternativ.
Notă:
Cuvintele-cheie trebuie să fie scrise cu minuscule.
Să ne uităm la exemplul anterior scris astfel:
52
1
2
3
4
5
6
var speed = 9; if (speed < 10) { document.write("Too slow..."); }else{ document.write("Too fast!"); }
Programul se comportă aproape la fel. Totuşi, observaţi că exemplul pe care l-am prezentat înainte
va returna rezultatul doar dacă variabila speed este un număr. Dacă variabila ar fi un string, nu s-
ar întâmpla nimic, în timp ce, în cazul în care vom folosi else (ca în acest exemplu), blocul
alternativ se execută întotdeauna când condiţia testată nu este îndeplinită. De foarte multe ori, acest
comportament poate fi extrem de util.
Să analizăm următorul exemplu: Trebuie să verificăm dacă utilizatorul a introdus parola de acces
corectă (pass variabil). Dacă variabila este corectă, va apărea mesajul „Bun venit”, iar în celălalt
caz mesajul „Parolă greșită...”
1
2
3
4
5
6
var pass = "myPass1"; if (pass === "myPass1") { document.write("Welcome"); }else{ document.write("Wrong password..."); }
Să revenim acum la exemplul care analizează viteza:
1
2
3
4
5
6
var speed = 9; if (speed < 10) { document.write("Too slow..."); }else{ document.write("Too fast!"); }
Este clar că aici avem două scenarii posibile. Primul este cel care se execută dacă condiția este
îndeplinită, iar celălalt, care se execută în cazul în care condiția nu este îndeplinită. Dar ce se va
întâmpla dacă am dori să introducem un al treilea scenariu posibil?
Să ne imaginăm următoarea cerere: Trebuie scris codul care verifică variabila speed şi:
dacă valoarea ei este sub 10, să apară mesajul „Too slow...”;
dacă speed este cuprinsă în intervalul 10 şi 80, să apară mesajul „Regular speed”;
dacă speed este peste 80, să apară mesajul „Too fast!”;
în orice alt caz să apară „Incorrect variable”.
Pentru a realiza acest lucru, trebuie să testăm niște condiții suplimentare. În aceste cazuri, poate fi
utilizată comanda else if. Să ne uităm mai întâi la reprezentarea grafică:
53
Imaginea 7.3.
Să explicăm comportamentul unei astfel de structuri. În primul rând, se verifică prima condiție și,
dacă această condiție este îndeplinită, se execută Blocul de cod 1, după care structura se
abandonează. Doar dacă prima condiție nu este îndeplinită, se trece la testarea altei condiții. Dacă
a doua condiție este îndeplinită, se execută blocul ei de cod și structura se abandonează. În final,
în cazul în care niciuna dintre cele două condiții nu este îndeplinită, se execută blocul de cod
alternativ (else).
Acest lucru se poate scrie astfel:
1 if (prima condiţie) {
54
Blocul de cod care se execută dacă prima condiţie este îndeplinită;
1 }else if(a doua condiţie){
Blocul de cod care se execută dacă a doua condiţie este îndeplinită;
1 }else if(a treia condiţie){
Blocul de cod care se execută dacă a treia condiţie este îndeplinită;
1 }else{
Blocul de cod alternativ care se execută dacă nicio condiţie nu este îndeplinită.
1 }
Să vedem acum sintaxa acestui exemplu:
1
2
3
4
5
6
7
8
9
10
var speed = 50; if (speed < 10) { document.write("Too slow..."); }else if(speed <= 80){ document.write("Regular speed."); }else if(speed > 80){ document.write("Too fast!"); }else{ document.write("Incorrect variable"); }
Notă:
Spre deosebire de alte limbaje de programare, în JavaScript nu este permis să se scrie cuvintele-
cheie else if împreună sau într-un cuvânt (elseif).
Să încercăm acum, grație cunoștințelor pe care le-am dobândit, să construim o structură de testare
a condițiilor puțin mai complexă. Deoarece în blocul de cod care se execută în if, else if sau
else putem scrie orice cod JavaScript, asta înseamnă că în aceste blocuri putem efectua o ramificare
internă:
1
2
3
4
5
6
7
if (condiţie1){ bloc cod 1; }else{ if (condiţie2){ bloc cod 2; }else{ bloc cod 3; } }
55
8
9
Să analizăm această situație. În cazul în care condiţia 1 este îndeplinită, se va executa blocul de
cod 1. În cazul în care condiția nu este îndeplinită, ramificația externă trece la blocul de cod else,
în care se află ramificația internă. Dacă condiţia 2, care este scrisă în ramificația internă, este
îndeplinită, se execută blocul de cod 2. Dacă nici această condiție nu este îndeplinită, se execută
blocul de cod 3.
Putem îmbunătăţi exemplul anterior astfel:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var speed = -1; if (speed < 10) { if (speed < 0) { document.write("You're moving backwards."); }else if(speed == 0){ document.write("No movement."); }else{ document.write("Too slow..."); } }else if(speed <= 80){ document.write("Regular speed."); }else if(speed > 80){ document.write("Too fast!"); }else{ document.write("Incorrect variable"); }
În acest caz, dacă variabila speed are o valoare mai mică de 10, are loc verificarea internă a
variabilei. Dacă condiţia internă este îndeplinită, respectiv dacă viteza este mai mică decât 0, va
apărea mesajul: ”You're moving backwards.” Dacă viteza este egală cu 0, se afişează mesajul ”No
movement”, iar dacă niciuna dintre condiții nu este îndeplinită, va apărea mesajul:
1 „Too slow...“.
Scrierea codului pe o singură linie
Uneori, codul pe care dorim să-l executăm, în cazul în care condiția este îndeplinită, este atât de
simplu, încât îl putem scrie pe o singură linie de cod. Atunci, nu suntem obligați să punem
paranteze acolade, respectiv să definim blocul de cod. Să vedem exemplul:
1
2
3
var x = 1;
if (x == 1) document.write("YES");
56
Deși codul este valid, evitați folosirea acestei sintaxe, cel puțin la începutul carierei dvs. de
programator, deoarece trebuie să acordați o atenție sporită sintaxei când scrieți codul, iar erorile
sunt frecvente.
Ramificarea condiţionată – switch case
Modul precedent de condiţionare a executării unui bloc de cod este corect, dar nu şi foarte elegant
când se ajunge la o sumedenie de alternative de tip else, iar pentru cazurile în care există alternative
multiple, se foloseşte o structură mai clară, numită switch case. Cu alte cuvinte, putem spune că
această structură este ideală pentru testarea unei variabile sau declarații care ar putea avea mai
multe valori așteptate. Să luăm, de exemplu, necesitatea ca în cod să fie testată variabila care ar
trebui să conțină numele zilelor săptămânii. Este clar că ne putem aștepta doar la șapte valori.
Să vedem mai întâi reprezentarea schematică:
Imaginea 7.4.
Deci, am ajuns la o expresie şi, în funcție de cazul în care se suprapune, se execută blocul de cod.
Dacă nu există suprapunere, se execută blocul de cod default.
57
Să analizăm acum sintaxa pentru switch:
1
2
3
4
5
6
7
8
9
10
switch (expresie) { case valoare1: //Blocul de cod care se va executa dacă expresia şi valoarea 1 se
suprapun break; //Cuvântul-cheie cu care se întrerupe executarea codului în
structura switch case valoare2: //Blocul de cod care se va executa dacă expresia şi valoarea 2 se
suprapun break; default: //Blocul de cod care va fi executat dacă nu există alte suprapuneri }
După cum putem observa, sintaxa începe cu cuvântul-cheie switch, după care, între paranteze
obişnuite setăm expresia sau variabila pe care o testăm. Apoi, între paranteze acolade vom defini
blocul de cod switch. În cadrul blocului, vom defini cazurile de utilizare, specificând cuvântul-
cheie case, după care stabilim o valoare posibilă pentru expresia sau variabila pe care o testăm.
După două puncte, urmează blocul de cod care se va executa dacă se ajunge la o suprapunere.
Blocul de cod ar trebui să se încheie cu comanda break, pentru a întrerupe executarea ulterioară a
codului. Dacă comanda break nu a fost stabilită, întregul cod din cadrul blocului de cod switch se
va executa indiferent dacă nu există nicio suprapunere în următoarele cazuri. Dacă vrem să definim
codul care se va executa dacă nu există nicio suprapunere, vom folosi cuvântul-cheie default (la
fel cum am utilizat anterior condiţia else).
Pentru claritate, să analizăm un exemplu real:
1
2
3
4
5
6
7
8
9
10
11
var x = 1; switch(x){ case 0: document.write("x is 0"); break; case 1: document.write("x is 1"); break; default: document.write("Unknown value."); }
În primul rând, am definit variabila x căreia îi vom atribui valoarea 1. Apoi, vom crea structura
switch specificând cuvântul-cheie. Între paranteze obişnuite, vom specifica variabila x, deoarece
în continuare vrem să îi testăm valoarea. Vom deschide paranteze acolade și vom defini primul
eveniment așteptat cu ajutorul cuvântului-cheie case. După acest cuvânt-cheie urmează spațiu,
apoi valoarea posibilă pentru x. În primul caz al exemplului nostru, valoarea este 0. După
specificarea valorii punem două puncte, după care definim blocul de cod care se va executa dacă
x are valoarea 0. Nu dorim ca blocul de cod să se execute în continuare şi, dacă există o
suprapunere, setăm comanda break cu care ieșim din bucla switch. Aceeași procedură se aplică şi
58
în următorul caz. În final, vom seta cuvântul-cheie default, după care nu definim o valoare
specifică, ci vom pune imediat semnul două puncte. Acest bloc de cod se va executa dacă nu există
nicio suprapunere în cazul 0: şi cazul 1:.
Notă:
Blocul de cod default se setează, prin convenţie, la sfârşitul codului switch, dar aceasta nu trebuie
să fie o regulă. Această parte de cod poate fi setată oriunde, dar dacă blocul de cod default nu este
setat la sfârşit, trebuie adăugată în mod obligatoriu comanda break. Acest exemplu va funcţiona la
fel ca şi cel precedent:
1
2
3
4
5
6
7
8
9
10
11
12
var x = 3; switch(x){ case 0: document.write("x is 0"); break; default: document.write("Unknown value."); break; case 1: document.write("x is 1"); break; }
Există încă un lucru foarte important pe care trebuie să-l avem în vedere atunci când vorbim despre
controlul switch. De fapt, logica acestei funcționalități este de aşa natură încât testarea se face prin
identitatea a două valori (===). Cu alte cuvinte, nu este suficient să existe o suprapunere doar în
funcție de valori, ci și de tip. Pentru a demonstra acest lucru, să analizăm următorul caz:
1
2
3
4
5
6
7
8
9
10
11
12
var x = "0"; switch(x){ case 0: document.write("x is 0"); break; case 1: document.write("x is 1"); break; default: document.write("Unknown value."); break; }
După executarea acestui cod, pe ecran apare scris următorul rezultat: „Unknown value”. Acest
lucru s-a întâmplat pentru că variabila x este de tip string, în timp ce în primul caz așteptăm un
număr, iar aici nu există nicio suprapunere.
59
Switch – suprapuneri multiple
Uneori, pentru a executa acelaşi bloc de cod trebuie să asigurăm suprapunerea multiplă a mai
multor valori posibile pentru expresia pe care o testăm. Pentru a explica acest lucru, vom stabili
următoarea cerință de utilizator: Trebuie să se creeze structura switch, care va testa valoarea
variabilei x. Dacă x are valorile 0, 1 sau 2, pe pagină apare „YES”, în timp ce pentru orice altă
valoare a variabilei x trebuie să apară scris „NOT”.
Această cerință de utilizator se poate rezolva în modul deja descris, prin utilizarea structurii switch,
dar ar mai fi nevoie de tastarea aceluiaşi cod (codul pentru scrierea mesajului „YES”) de trei ori.
Cum în programare nu este bine aproape niciodată ca același cod să se afle în două locuri, trebuie
să evităm acest lucru. Pentru a rezolva această situaţie, vom lua în considerare două modalități.
Prima modalitate
Această metodă de rezolvare a problemei suprapunerii multiple, este folosită de switch care va
începe să execute codul atunci când întâlnește o suprapunere, și nu va întrerupe nimic până când
nu întâlnește comanda break:
1
2
3
4
5
6
7
8
9
10
11
var x = 1; switch(x){ case 0: case 1: case 2: document.write("YES"); break; default: document.write("NOT"); break; }
A doua modalitate
Putem rezolva problema prin utilizarea unor expresii mai complexe într-un caz case. Astfel, ne
folosim cunoștințele deja dobândite despre operatorii logici și operatorii de comparație:
1
2
3
4
var x = 1; switch (true) { case x >= 0 && x <= 3: document.write('YES'); break;
60
5
6
7
8
default: document.write('NOT'); }
Observaţi faptul că în condiţia switch am scris literal true logic şi apoi în cazul case am setat
expresia care, după cum știm deja, va returna valoarea true sau false. Dacă expresia este adevărată,
va fi returnată valoarea true care se va suprapune cu expresia pe care am specificat-o între
paranteze obişnuite. Dacă valoarea expresiei este false, nu va exista nicio suprapunere și blocul de
cod default se va executa.
Operatorul condiţional ? :
În JavaScript, operatorul condițional este singurul operator care manipulează trei operanzi. Acesta
este motivul pentru care uneori mai este numit şi operator ternar.
Putem defini operatorul ternar în felul următor:
1 (name == "Ann") ? "You are Ann" : "We don't know you";<span style="font-size: 14px; text-align: justify;"> </span>
În primul rând, verificăm dacă valoarea variabilei este egală cu "Ann"; dacă este, returnează textul
"You are Ann", în caz contrar returnează textul "We don’t know you". Deci, după semnul "?"
urmează ceea ce se întâmplă dacă condiția este îndeplinită (true), iar după semnul ":" ce se întâmplă
dacă condiția dată nu este îndeplinită.
Haideţi să vedem cum funcţionează operatorul ternar într-un exemplu simplu:
1
2
3
varname="Ann"; var i=(name == "Ann") ? "You are Ann" : "We don't know you"; document.write(i);
Definim variabila a cărei valoare vrem să o testăm în condiţie. De exemplu, o variabilă care are
valoarea "Ann". Apoi, definim condiţia și variabila care va păstra valoarea de executare a
operatorului ternar și, la final, scriem valoarea acelei variabile pe ecran, pentru a vedea rezultatul
executării operatorului ternar.
Să vedem următorul cod:
1
2
3
4
5
6
7
vara=10; if(a==10){ var b=a; }else{ var b=150; } document.write(b);<span style="font-size: 14px; text-align:
justify;"> </span>
61
Este evident ce face codul: atribuie valoarea 10 variabilei a, apoi verifică dacă a este 10. Dacă este,
atunci atribuie variabilei b valoarea variabilei a, iar dacă nu este, atribuie variabilei b valoarea
150. La final, emite valoarea variabilei b pe pagină.
Acest exemplu este valabil şi va funcţiona fără nicio problemă. Dar, cu ajutorul operatorului ternar,
timpul de executare poate fi scurtat considerabil.
Iată şi exemplul:
1
2
3
var a=10; var b=(a==10) ? a : 150; document.write(b);
Acest program, deşi mult mai scurt, produce un rezultat identic cu cel precedent. Să analizăm a
doua linie (care înlocuieşte întregul bloc if else din exemplul precedent):
1 var b =
Este un operator obişnuit de atribuire. Valoarea părţii din dreapta va fi atribuită variabilei din
stânga:
1 (a==10)
Condiţia relevantă pentru decizia alternativă este:
1 ? a : 150;
În cazul în care condiția este îndeplinită și a == 10, returnează variabila a, în caz contrar, returnează
numărul 150. Acest rezultat este stocat în variabila b, așa că obținem același efect ca și când am fi
folosit în exemplu comanda if-else din exemplul precedent.
Alternative
După semnul întrebării (a), se află alternativa care va fi luată în considerare dacă condiţia este
îndeplinită, iar după două puncte (150), se află alternativa pentru cazul în care condiţia nu este
îndeplinită.
Astfel, la final obţinem ceva de genul:
Atribuie variabilei b (dacă a este egală cu 10) valoarea a, iar în caz contrar, valoarea 150:
1 b = (a==10) ?a : 150;<span style="font-size: 14px; text-align:
justify;"> </span>
Aceste comparaţii sunt utile când vrem să acordăm valorile subînţelese variabilelor, dacă acestea
nu sunt iniţializate. Dar mai multe informaţii în acest sens, în capitolul despre funcţii.
62
1 b=(a!=null) ? a : 120;
Buclele
Unitate: 8 din 19 00:18:52
+Rezumat
Subiectul acestei lecţii este lucrul cu buclele. Vorbim despre modurile de repetare multiplă a unui
anumit bloc. Repetarea multiplă a blocurilor se poate realiza în două moduri: repetarea planificată
a unei logici care se va repeta de mai multe ori, dar și mai important, în mai multe locuri diferite -
ceea ce, în general, reprezintă funcţiile - şi repetarea ad-hoc a unui bloc care are loc undeva în cod.
După aceea, programul merge mai departe şi nu se mai întoarce niciodată la partea respectivă.
(Vorbim ipotetic. Bineînţeles că oricând putem face programul să revină la orice parte.) Din punct
de vedere teoretic, a doua descriere reprezintă buclele.
Ce este mai exact bucla, pe lângă faptul că reprezintă un instrument foarte puternic de programare?
Bucla este un control care face posibilă repetarea unui anumit bloc de cod de atâtea ori câte a
stabilit utilizatorul.
Pur şi simplu, dacă dorim ca programul nostru să scrie ceva pe ecran de cinci ori, notăm:
document.write("Hello");
document.write("Hello");
document.write("Hello");
document.write("Hello");
document.write("Hello");
Dar i-am putea transmite şi să facă ceva de 5 ori:
document.write("Hello");
Astfel, nu numai că scurtăm codul cu câteva linii, dar putem și să controlăm, prin specificarea unui
număr, de câte ori se va repeta un bloc. În general, această logică este, de fapt, şi logica pe baza
căreia funcţionează bucla.
În ceea ce priveşte clasificarea buclelor, distingem câteva categorii. Prima categorie este
reprezentată de buclele care ne cer să ştim dinainte numărul de iteraţii (iteraţia fiind, de fapt, fiecare
trecere a blocului de cod prin buclă), iar a doua, de cele care nu solicită acest lucru. De asemenea,
după modul de executare, buclele se împart în bucle for, while şi foreach.
63
Bucla while
Acest tip de buclă va executa blocul de cod definit din nou și din nou, până când se îndeplinește
condiția pe care o testează. Să vedem cum poate fi aceasta afișată grafic:
Imaginea 8.1. Bucla while
Bucla while aparţine categoriei care nu ne cere să cunoaștem în prealabil numărul de iteraţii. Pur
şi simplu, aceasta se execută de atâtea ori câte îi permite blocul care se execută sub ea. Bucla while
necesită o anumită condiţie, care se introduce ca parametru în momentul iniţializării ei şi care se
execută atâta timp cât este îndeplinită condiţia. Pentru a permite executarea codului în cadrul buclei
while, trebuie să fie îndeplinită condiția definită la începutul comenzii while. Condiția pe care o
definim la crearea buclei while nu este diferită de condițiile pe care le-am folosit la definirea
comenzii if. Condiția are un rol foarte important, deoarece uneori trebuie să întrerupem executarea
buclei.
Să analizăm sintaxa:
while (condiţie) {
//Blocul de cod care se va executa dacă condiţia este îndeplinită
}
Iată un exemplu real:
varx=0;
while(x<5)
{
document.write("Hello");
64
x=x+1;
}
Rezultatul acestui exemplu este identic cu rezultatul exemplului de mai sus, unde am repetat de 5
ori linia document.write("Hello");.
Observăm că aici condiţia este ca valoarea variabilei x să fie mai mică decât 5, doar în acest caz
condiţia se execută şi blocul se inițializează. De asemenea, observăm că în cadrul blocului, după
linia de scriere, controlăm valoarea variabilei x, prin mărirea cu unu la fiecare iteraţie. În acest fel,
permitem ca bucla să se execute de un număr limitat de ori.
Aşadar, singura condiţie pe care trebuie să o respectăm pentru a intra în această buclă este ca x să
fie mai mic decât 5. După aceea, restul se controlează din buclă. Acest lucru poate fi un proces
inadecvat, deoarece ghidarea manuală a variabilei prin buclă poate scăpa de sub control şi astfel
fluxul executării poate fi perturbat.
Notă:
Nu încercaţi să porniţi acest exemplu în browser-ul dvs.!
var x=0;
while(x<5)
{
document.write("Hello");
}
Seamănă cu cel anterior, cu excepţia faptului că aici am omis linia în care valoarea x se măreşte
cu unu. Astfel, am dezactivat îndeplinirea condiţiei şi am creat o aşa-numită buclă moartă,
respectiv o buclă care nu încetează niciodată să se execute. Dacă se întâmplă ca în propriul cod să
aveți o buclă moartă, lansarea ei va duce la întreruperea programului. Interpretul JavaScript
percepe această linie de cod ca şi când am fi scris while (true). Condiția este întotdeauna îndeplinită
și, astfel, nu vom ieși niciodată din blocul de comenzi din cadrul buclei. Deşi browser-ele au
mecanisme care recunosc aceste cazuri (şi oferă utilizatorului posibilitatea de a întrerupe
executarea script-ului blocat într-o buclă moartă), ele trebuie tratate cu grijă.
Expresia condiţională din bucla while este de tip boolean, așa că poate avea şi o structură mai
complexă. De exemplu: while(x<5 &&x>0) etc. Putem folosi diferiţi operatori logici pentru a
defini condițiile. Cei mai des utilizați operatori sunt cei logici și (&&), care presupun îndeplinirea
fiecărui segment al condiţiilor pe care această comandă se conectează, precum şi cei logici sau (||),
care presupun îndeplinirea unuia dintre segmentele condiţiilor date. De exemplu, condiția
while(x<5 &&x>0) va fi îndeplinită numai dacă variabila x este în același timp mai mică decât 5
și mai mare decât 0, în timp ce comanda while (a<5 || a>0) va fi îndeplinită dacă variabila x este
mai mică decât 5 sau mai mare decât 0. Deci, este suficient ca în al doilea caz să fie îndeplinită
doar o singură condiție. Mai multe despre operatori puteţi citi într-una din lecțiile precedente.
65
Bucla do…while
Bucla do…while este foarte asemănătoare buclei while, cu diferenţa că blocul de cod al buclei se
execută întotdeauna cel puțin o dată, indiferent de îndeplinirea condițiilor. Și aceasta este execuția
do while, respectiv mai întâi se execută iteraţiile şi abia apoi se verifică şi condiţiile. Acest mod de
executare se folosește atunci când vrem să executăm comanda în cadrul blocului doar o dată,
indiferent de condiție. Bucla do while ne permite, mai întâi, să executăm un bloc de comenzi din
cadrul comenzii do și apoi să trecem prin condiţie. Executarea ulterioară a comenzii, respectiv
dacă o parte din blocul do se va executa din nou, depinde de condiții.
Să analizăm mai întâi aspectul grafic:
Imaginea 8.2. Bucla do...while
Privind această schemă, putem trage concluzia că bucla blocului de cod din orice caz va fi
executată o dată. Abia după executarea codului, se testează condiţia. Dacă condiția nu este
îndeplinită, bucla este abandonată. Pe de altă parte, dacă condiția este îndeplinită, se execută din
nou blocul de cod, după care condiția se testează din nou. Un astfel de circuit se continuă până
când este îndeplinită condiţia sau până când, cu comanda break, abandonăm bucla do…while.
Acum să analizăm sintaxa:
do{
//Blocul de cod
}while(condiţia care se testează);
Observaţi că sintaxa este foarte simplă și foarte asemănătoare cu bucla precedentă. Mai întâi, setăm
cuvântul-cheie do, după care, în cadrul parantezelor acolade (pentru declarații de o linie, aceste
paranteze nu sunt necesare, dar sunt recomandate), vom defini codul care va fi executat. Apoi,
66
vom seta cuvântul-cheie while, după care între paranteze obişnuite definim condiția care se
testează.
Acum, să aplicăm aceasta pe un exemplu real:
var x = 10;
do {
document.write("Hello");
x++;
} while(x<0);
Atunci când se încarcă parser-ul, întâlnim o declarație a variabilei x căreia îi atribuim valoarea 10.
După aceasta, urmează comanda do al cărei bloc de cod se execută imediat. Deci, în acest moment
pe pagină a apărut mesajul "Hello". Doar acum se verifică condiția. Se constată că această condiție
nu este îndeplinită și bucla do...while este abandonată. Totuşi, blocul de cod va fi executat
indiferent dacă condiţia nu a fost îndeplinită niciodată.
Bucla for
Spre deosebire de bucla while, bucla for ne solicită să ştim cu exactitate de câte ori se va executa
un anumit bloc. Acest lucru trebuie înţeles în mod ipotetic, deoarece, atunci când începe
iniţializarea buclei for, de obicei o parte se formează după dimensiunea unei structuri prin care
vrem să trecem cu bucla (şir).
Să analizăm mai întâi grafic comportamentul buclei for:
67
Imaginea 8.3. Bucla for
Deci, de la început, bucla iniţializează variabila care va fi un numărător (deşi aici se pot iniţializa
şi alte variabile). După aceea, se verifică condiţia. Dacă condiţia este îndeplinită, se execută blocul
de cod definit în corpul buclei. După executarea codului, se efectuează incrementarea
numărătorului (totuşi, acest lucru nu trebuie să fie doar incrementare, ci orice operație pe
numărător), după care condiţia se verifică din nou.
O astfel de trecere prin buclă se numește iteraţie. Când testarea condițiilor returnează valoarea
false, executarea buclei se întrerupe.
Sintaxa for (inițializarea; condiţia; declaraţia_finală){
//Blocul de cod
68
}
Iniţializarea – Forma de bază și cea mai comună pentru bucla for presupune că, în partea codului
prezentat mai sus, ca iniţializare se definește o variabilă (de obicei, variabila i), care va servi ca
numărător. În cele mai multe cazuri, este util ca valoarea inițială a acestei variabile să fie 0,
deoarece, adesea, cu ajutorul acestei bucle se trece printr-un şir a cărui indexare începe cu zero. Pe
lângă inițializarea variabilei care va fi numărător, aici putem defini şi alte variabile, dacă sunt
necesare.
Condiţia – În această parte, se defineşte expresia al cărei rezultat, în urma execuţiei, ar trebui să
returneze o valoare booleană. Condiția se construieşte cel mai frecvent prin compararea unei valori
cu variabila definită în numărător. În cazul în care această condiție este îndeplinită, se continuă
executarea buclei for, în caz contrar executarea buclei for se întrerupe.
Declaraţia finală – Codul definit în această parte se execută la sfârşitul fiecărei iteraţii. Cel mai
frecvent se foloseşte pentru mărirea (sau altă modificare) numărătorului.
Notă:
Iniţializarea, condiţia şi declaraţia finală se separă în mod obligatoriu prin punct şi virgulă (;). În
cazuri speciale, este permisă omiterea oricărui cod dintr-o parte (sau chiar în toate cele trei părţi),
dar semnul ; dintre paranteze, trebuie totuși să existe.
Exemplu:
for ( ; ; ){
//Bloc de cod
}
Nu scrieţi un astfel de cod, dacă nu sunteţi absolut siguri asupra a ceea ce doriţi să faceţi cu
exactitate.
Să analizăm acum un exemplu real de cod:
for (var i = 0; i < 10; i++) {
document.write(i);
}
După executarea acestui cod, pe ecran va fi afișat rezultatul: 0123456789.
Mai înainte, am setat cuvântul-cheie for, cu care începem bucla. După aceea, am setat între
paranteze inițializarea, condiţia și incrementarea. Cu ocazia iniţializării, am declarat
variabila i, care ne va servi drept numărător al iterației. Apoi, vom defini condiția care cere ca
numărătorul să fie mai mic decât numărul 10. În final, vom efectua incrementarea
numărătorului (mărire cu unu). Între paranteze acolade, se definește blocul de cod care va fi
executat în fiecare iteraţie.
69
Pentru a observa că inițializarea şi declaraţia finală pot avea o construcţie mai complexă, analizăm
următorul exemplu:
for (var i = 0, j = 10; i < 10; i++, j--) {
document.write(i + "<br/>");
document.write(j + "<br/>");
}
De data aceasta, în momentul inițializării declarăm două variabile, variabila i şi variabila j.
Variabila i are valoarea inițială 0, iar variabila j are valoarea inițială 10. La fiecare iteraţie,
variabila i se măreşte cu unu, iar variabila j se reduce, tot cu 1 (i++, j--). În corpul buclei, setăm
două linii de cod. Prima linie scrie valoarea variabilei i. Observați că am adăugat un tag HTML
<br/> pentru a afișa rezultatele pe un rând nou. La fel, scriem și valoarea variabilei j. Rezultatul
pe pagină este:
0
10
1
9
2
8
3
7
4
6
5
5
6
4
7
3
70
8
2
9
1
Bucla for…in
Deoarece în JavaScript şirurile sunt un anumit tip de obiect, putem folosi bucla for…in pentru a
accesa fiecare element al şirului. De altfel, această buclă accesează fiecare proprietate a obiectului.
Putem observa şirul indexat ca un obiect al cărui nume este proprietatea indicelui.
Să analizăm sintaxa:
for (variabila în obiect) {
//Blocul de cod
}
În cazul nostru, variabila marchează declaraţia unei variabile numită arbitrar, care la fiecare iterație
va prelua valoarea indicelui şirului. Aceasta este urmată de cuvântul-cheie in, după care vom defini
prin care obiect (în cazul nostru, şir) vrem să trecem. În final, vom defini blocul de cod care se va
executa pentru fiecare iterație. Ideea este ca în blocul de cod să folosim variabila pentru a accesa
elementele şirului.
Exemplu:
var arr = ["Belgrad", "Paris", "Berlin"];
for (var city in arr) {
document.write(arr[city] + " ");
}
După cum putem vedea, în primul rând este definită variabilă arr, care este, de fapt, şirul prin care
vrem să trecem. Șirul are trei elemente. Pentru a trece prin toate elementele şirului, folosim bucla
for…in. În cadrul parantezelor obișnuite, vom declara variabila city, care în fiecare iterație va avea
valoarea indicelui elementului şirului până la care a ajuns bucla (în prima iterație, city va fi 0, în a
doua iteraţie, 1, în a treia, 2 etc. ...). După cuvântul-cheie in, specificăm identificatorul pentru şirul
prin care trecem (arr). Acum, ajungem la corpul buclei unde apare:
document.write(arr[city] + " ");
În această linie de cod se poate să nu vă fie clar arr[city]. Deoarece variabila city din fiecare iterație
este un alt număr care corespunde următorului indice din şir, este clar că în acest fel ne asigurăm
ca pe pagină să fie scrise toate elementele şirului.
Ieşirea pe pagină este: Belgrad, Paris, Berlin.
71
Comenzile break şi continue
Uneori, dorim ca pe baza anumitor condiții să controlăm fluxul buclei în cadrul blocului ei. Atunci,
putem folosi cuvintele-cheie continue şi break. Cuvântul-cheie continue întrerupe iterația curentă
și trece la alta, în timp ce cuvântul-cheie break părăseşte bucla.
Următorul exemplu va prezenta la ieşire numerele de la 0 până la 50, dar, în final, valoarea i va fi
100:
for(var i=0;i<100;i++){
if(i>50){
continue;
}else document.write(i + " ");
}
document.write("<br/>" + i);
În acest exemplu, cu comanda continue vom trece de fiecare dată la următoarea iterație, ignorând
restul comenzii blocului de sub linia continuă. Prin urmare, nu se va efectua înscrierea valorilor
pentru toate variabilele i care sunt mai mari de 50. În final, în afara buclei vom scrie valorile
variabile i, pentru a ne asigura că valoarea ei este 100. Scrisul afișat pe pagină va fi:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
100
Următorul exemplu va prezenta, de asemenea, numerele de la 0 la 50, dar, în final, valoarea i va fi
51, pentru că după numărul 50 bucla va fi abandonată:
for(var i=0;i<100;i++){
if(i>50){
break;
}else document.write(i + " ");
}
document.write("<br/>" + i);
Acum, pe ecran apare:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
51
Metode de utilizare a șirurilor
Unitate: 9 din 19 00:26:58
+Rezumat
72
Până acum, am stabilit cum să plasăm un element în şir şi cum să citim elementele din şir. Dar
aceste proceduri nu sunt foarte automatizate şi nu fac nicio deosebire între şiruri și celelalte
variabile. De aceea, adevărata putere a şirurilor se vede abia atunci când sunt manipulate prin
diferite tipuri de bucle. Despre bucle am vorbit deja în lecţia precedentă când am menţionat buclele
for şi for…in. Acestea sunt foarte utile atunci când este vorba de valabilitatea şirurilor, motiv
pentru care le vom folosi în lecţia de acum. Pe lângă manipularea şirurilor cu ajutorul buclei, aici
vom mai menţiona și câteva dintre cele mai folosite metode de lucru cu şirurile.
Proprietăţile şi funcţiile şirurilor
După ce am utilizat un şir, simțim nevoia să-i cunoaștem proprietățile. În general, dacă putem să
citim şirul, putem ajunge uşor și la acestea. Totuşi, majoritatea limbajelor de programare presupun
că programatorul le va utiliza şi conţin un pachet încorporat de proprietăţi şi funcţii de manipulare
a şirurilor. În majoritatea limbajelor, aceste funcţii şi proprietăţi sunt identice în ceea ce privește
funcţionalitatea, diferența dintre ele fiind doar de nume.
Înainte de a explica principalele proprietăţi şi funcţii ale şirurilor, trebuie să evidenţiem câteva
detalii legate de acestea. De fapt, în JavaScript există obiecte care au diferite proprietăţi şi metode.
Proprietăţile ne oferă informații despre obiect, în timp ce metodele sunt funcții pe care le putem
apela asupra obiectului. Aceste informații vă pot părea confuze, dar nu trebuie să vă faceţi griji.
Pentru moment este suficient să ştiți că şirul, la fel ca obiectul, este un set de valori. În timp ce în
cazul obiectelor, proprietăţile au nume, în cazul şirurilor, acestea sunt numere care se numesc
indecşi. Despre indecşi am vorbit mai devreme şi acum deja ştiţi că se folosesc pentru localizarea
elementului într-un şir. Tocmai am menţionat numărul de elemente din şir. Aceasta este informaţia
(proprietatea) care ne spune mai multe despre şiruri. În continuare vom discuta despre cum putem
afla informaţii despre numărul de elemente dintr-un şir.
Cum confirmăm lungimea şirului – length
Prima utilizare a șirurilor constă în calcularea dimensiunii şirului în sine, respectiv a numărului
său de membri. Această informaţie se obţine uşor cu proprietatea length:
1
2
var arr=[3,5,2,6,1,7];
document.write(arr.length);<span style="font-size: 14px; text-align:
justify;"> </span>
Pentru a ajunge la o proprietate a şirului, menţionăm identificatorul şirului (numele şirului
respectiv), setăm punctul şi menţionăm proprietarea care ne interesează. Dat fiind că în acest caz
pe noi ne interesează lungimea şirului, am scris arr.length.
Rezultatul este 6.
Proprietatea length are ca valoare un număr întreg şi joacă un rol important în trecerea prin toate
elementele şirului, atunci când nu ştim dinainte numărul final al elementelor şirului. De exemplu,
când în buclă definim condiţia referitoare la câte iteraţii va executa bucla, putem folosi funcţia
73
length. De asemenea, dacă vrem să accesăm ultimul element al şirului și nu ştim numărul exact de
elemente conţinute de şir, putem face următoarele:
1
2
var arr=[3,5,2,6,1,7];
document.write(arr[arr.length-1]);<span style="font-size: 14px; text-align:
justify;"> </span>
Este important să observaţi diferenţa dintre indexul după care sunt numerotate elementele şi
numerele de elemente din şir. Numărul care reprezintă lungimea şirului este egal cu indexul
ultimului element, deoarece numerotarea elementelor, când am definit indexul, începe de la zero,
aşadar numărul total al elementelor este întotdeauna mai mare cu unu decât ultimul index. În acest
caz, numărul de elemente ale şirului (length) este 6, deşi ultimul index al şirului este, de fapt, 5.
Astfel, valoarea ultimului index se obţine atunci când din lungime scădem valoarea 1. Rezultatul
acestui exemplu afișează pe ecran cifra 7, deoarece este ultimul element.
În același mod, cu ajutorul opţiunii length putem adăuga în șir valori noi. Deoarece şirul.lengh
afișează deja valoarea ultimului index mărit cu unu (știm că numerotarea indexului începe de la
zero), este suficient să atribuim o nouă valoare elementului şirului care are valoarea lungimii
şirului. Proprietatea length facilitează găsirea adevăratului loc gol (dacă vrem să adăugăm alte
valori în şir):
1 arr[arr.length]=6;<span style="font-size: 14px; text-align:
justify;"> </span>
Adăugăm încă un 6 la şirul existent, aşadar acum şirul este 3, 5, 2, 6, 1, 7, 6. Astfel, am mărit
numărul de elemente ale şirului cu unu, adăugând un element nou. Acum şirul nostru conţine 7
elemente.
Cum concatenăm şirurile – concat()
Metoda concat() permite concatenarea şirurilor. Funcţia se foloseşte simplu: mai întâi menţionăm
variabila care va conţine elemente noi, apoi apelăm funcţia prin variabila în care vrem să aplicăm
unirea:
1
2
3
4
5
var arr1 = [1, 2];
var arr2 = [3, 4, 5];
var arr3 = [6];
var arr_all = arr1.concat(arr2,arr3);
document.write(arr_all);<span style="font-size: 14px; text-align:
justify;"> </span>
După această concatenare, şirul arr_all va conţine următoarele elemente: 1, 2, 3, 4, 5, 6.
74
Cum găsim poziţia unui string în şir – indexOf()
Această funcţie verifică şirul şi returnează indexul elementului căutat. Dacă elementul căutat nu
există în şir, metoda returnează valoarea -1.
Să analizăm următorul exemplu:
1
2
3
4
var arr = [5,8,2,4,7];
var num = arr.indexOf(4);
document.write(num);<span style="font-size: 14px; text-align:
justify;"> </span>
În primul rând, am definit şirul care conţine următoarele elemente: 5, 8, 2, 4 şi 7. Apoi, am definit
încă o variabilă (num) care va accepta valoarea returnată de metoda indexOf(), atunci când o
apelăm asupra obiectului arr şi îi atribuim ca parametru cifra 4. Deci, apelând metoda indexOf
asupra şirului arr, practic verificăm dacă cifra 4 se află în şirul arr şi, dacă da, pe ce poziţie.
Deoarece cifra 4 se află, într-adevăr, în şirul nostru arr, metoda ne va returna poziţia sa. Să ne
reamintim că poziţiile elementelor încep de la zero, de aceea poziţia cifrei 4 este în acest caz 3. De
aceea, ca rezultat pe ecran apare cifra 3.
Notă:
Metoda indexOf astfel folosită va returna poziţia primului element din şir, cu care s-a suprapus.
Aceasta înseamnă că celelalte elemente vor fi omise, când metoda ajunge la rezultat. Iată un
exemplu în acest sens:
1
2
3
4
var arr = [5,8,2,4,7,8];
var num = arr.indexOf(8);
document.write(num);<span style="font-size: 14px;"> </span>
Afișarea de pe ecran este 1.
După cum putem vedea, cu această metodă am încercat să găsim poziţia cifrei 8 în şir. Metoda a
găsit cifra pe poziţia 1 şi imediat a returnat valoarea 1. Mai departe șirul nu mai este verificat, deşi
mai există un 8 pe ultima poziţie. Deci, rezultatul acestei metode ne oferă doar poziţia primului
element, pentru care se confirmă suprapunerea. La al doilea 8 se poate ajunge prin introducerea
celuilalt parametru pentru această metodă. Cu primul parametru, am stabilit câte poziţii în şir
trebuie să fie înainte de a începe căutarea.
Exemplu:
75
1
2
3
4
var arr = [5,8,2,4,7,8];
var num = arr.indexOf(8, 2);
document.write(num);<span style="font-size: 14px; text-align:
justify;"> </span>
Acum, în loc de un parametru, i-am atribuit funcţiei doi parametri (8 şi 2). Să ne reamintim că
parametrii se separă prin virgulă. În continuare, primul parametru (cifra 8) reprezintă elementul
din şir căutat, iar al doilea parametru (cifra 2) stabileşte de pe ce poziţie începem căutarea. În acest
caz, vor fi căutate următoarele elemente ale şirului:
1 var arr = [5,8,2,4,7,8];<span style="font-size: 14px; text-align:
justify;"> </span>
în timp ce elementele de pe poziţiile 0 şi 1 vor fi omise. Deoarece am sărit primul număr 8, căutarea
va găsi suprapunerea abia la finalul şirului şi va returna rezultatul 5, deoarece aceasta este poziţia
celui de-al doilea 8 în şir.
Dacă drept al doilea parametru am atribui un număr negativ, ar însemna că metoda va începe
verificarea de la poziţia care se primeşte atunci când se face mutarea de la capătul şirului, pentru
atâtea poziţii câte indică cifra de după semnul - . Să vedem un exemplu în acest sens:
1
2
3
4
var arr = [5,8,2,4,7,8];
var num = arr.indexOf(8,-2);
document.write(num);<span style="font-size: 14px; text-align:
justify;"> </span>
Acum, vor fi căutate următoarele elemente ale şirului:
1 var arr = [5,8,2,4,7,8];<span style="font-size: 14px; text-align:
justify;"> </span>
Mai rămâne ca în exemplu să arătăm că rezultatul căutării fără suprapunere va fi -1:
1
2
3
4
var arr = [5,8,2,4,7,8];
var num = arr.indexOf(10);
document.write(num);<span style="font-size: 14px; text-align:
justify;"> </span>
76
Deoarece în şirul arr nu există cifra 10, valoarea variabilei num este -1.
Notă:
String-ul se poate accesa la fel ca şirul, așa că putem căuta şi text. De exemplu, această metodă se
poate folosi pentru a căuta cuvintele în propoziţie.
De exemplu:
1
2
3
4
var text = "Greg works in a bank.";
var w = text.indexOf("bank");
document.write(w);<span style="font-size: 14px; text-align:
justify;"> </span>
După căutare, variabila w va obţine valoarea 16, deoarece aceasta este poziţia pe care apare
cuvântul bank.
Cum eliminăm ultimul element din şir – pop()
Această funcţie se foloseşte pentru a elimina ultimul element din şir. De asemenea, funcţia pentru
valoarea de returnare conține ultimul element care este eliminat. Aceasta înseamnă că rezultatul
metodei se poate atribui unei variabile noi, iar şirul în care am apelat-o va rămâne fără ultimul
element, a cărui valoare va fi atribuită variabilei. Iată prezentarea grafică:
Imaginea 9.1.
Să vedem acum exemplul scris în codul JavaScript:
1 var arr = [1,2,3,4];
77
2
3
4
var x = arr.pop();
document.write(x + "<br/>" + arr);
După cum putem vedea, la începul codului am definit şirul arr care are 4 membri (1, 2, 3, 4).
Apoi, definim variabila x, căreia îi atribuim rezultatul pe care îl obţinem în urma apelării metodei
pop() asupra şirului arr. Metoda aplicată pe şir elimină ultimul membru (cifra 4) şi îl returnează
variabilei x. Acum, şirul a rămas fără ultimul membru, iar variabila x a primit valoarea 4. Pentru
a demonstra asta, scriem valoarea variabilei x, apoi setăm tag-ul <br> datorită trecerii pe noul
rând şi, la final, scriem valoarea şirului. Rezultatul afișat pe ecran este:
4
1,2,3
Cum adăugăm un nou element la sfârşitul şirului – push()
Condiţional, am putea spune că metoda push() efectuează operaţia opusă metodei pop(). De fapt,
cu ajutorul metodei push() adăugăm un element nou (sau elemente noi) la sfârşitul şirului. După
executare, această metodă returnează o nouă lungime a şirului. Este logic că aici trebuie să
menţionăm ce element (sau elemente) vrem să adăugăm în şir și de aceea trebuie definiţi
parametrii.
Iată prezentarea grafică:
Imaginea 9.2.
Să vedem acum sintaxa:
1 var arr = [1,2,3];
78
2
3
4
var x = arr.push(4);
document.write(x + "<br/>" + arr);<span style="font-size: 14px;"> </span>
Observaţi că şirul arr posedă la început trei elemente (1, 2, 3), după care asupra acestui şir se
apelează metoda push(), căreia îi este distribuit un parametru (4). De aceea, metoda adaugă acest
element şirului. Acum şirul are 4 elemente (1, 2, 3, 4). După finalizarea cu succes a procesului de
adăugare a elementelor în şir, are loc numărarea membrilor, iar rezultatul este atribuit variabilei x.
La final, analizăm aceste valori, iar afișarea de pe ecran este:
4
1,2,3,4
Iată un exemplu de adăugare a unui număr mai mare de membri:
1
2
3
4
var arr = [1,2,3];
var x = arr.push(4,10,20,30,100);
document.write(x + "<br/>" + arr);<span style="font-size: 14px;"> </span>
Afișarea pe pagină este:
8
1,2,3,4,10,20,30,100
Cum eliminăm primul element din şir – shift()
Metodele pop() şi push() gestionează elementele de la sfârşitul şirului. În același fel, putem
manipula şi elementele de la începutul şirului cu ajutorul metodelor shift() şi unshift().
Metoda shift() apelată asupra şirului va duce la eliminarea primului element.
Iată prezentarea grafică:
79
Imaginea 9.3.
Sintaxa este următoarea:
Acum, vă vom prezenta exemplul din ilustraţia precedentă cu sintaxa JavaScript. Cu acest scop,
să presupunem că elementele din şir sunt numerele: 10, 20, 30 şi 40.
1
2
3
4
var arr = [10,20,30,40];
var x = arr.shift();
document.write(arr + "<br />" + x);<span style="font-size: 14px;"> </span>
În prima linie a codului, am definit denumirea șirului, respectiv identificatorul arr. În a doua linie
a codului, am schimbat metoda shift() şi am eliminat primul element din şir. În a treia linie, am
scris şirul şi variabila x pe pagină, iar rezultatul este:
20,30,40
10
După cum putem observa, şirul arr a rămas fără primul membru, iar variabila x a obţinut valoarea
care corespunde membrului eliminat din şir.
Notă:
Ceilalţi membri ai şirului, după executarea metodei shift(), îşi schimbă indecşii, așa că acum
elementul 20 are indexul 0, elementul 30 are indexul 1 etc.
Cum adăugăm un nou element la începutul şirului – unshift()
După cum cu metoda push() putem adăuga un nou element (sau mai multe elemente) la sfârşitul
şirului, tot așa cu metoda unshift() putem adăuga un nou element (sau mai multe) la începutul
şirului.
80
Să vedem prezentarea grafică:
Imaginea 9.4.
Iată și sintaxa:
Ca să prezentăm exemplul ilustraţiei cu sintaxă, vom folosi şirul care la început are trei elemente,
numerele: 20, 30 şi 40. Apoi, cu metoda unshift() vom adăuga elementul 10 la începutul şirului:
1
2
3
4
var arr = [20,30,40];
arr.unshift(10);
document.write(arr);<span style="font-size: 14px; text-align:
justify;"> </span>
Mai întâi am creat şirul, apoi asupra acestui şir, în a doua linie a codului, am apelat metoda unshift()
şi i-am distribuit ca parametru cifra 10. Această metodă adaugă noul element la începutul şirului
şi, când în a treia linie afișăm şirul, obţinem:
10,20,30,40
Spre deosebire de exemplul precedent, aici nu am avut variabila x, aşadar nu ştim ce returnează
metoda unshift() ca rezultat al activității sale apelate asupra şirului. Să vedem asta în
exemplul următor:
1
2
3
4
var arr = [20,30,40];
var x = arr.unshift(10);
document.write(arr + "<br/>" + x);<span style="font-size: 14px;"> </span>
Ieşirea pe pagină este:
81
10,20,30,40
4
Observăm că metoda a făcut acelaşi lucru, dar că acum variabila x are valoarea 4. Aceasta se
datorează faptului că, după activitatea sa, metoda unshift() returnează ca rezultat noua lungime a
şirului asupra căruia a fost apelată. Şirul nostru arr a avut la început trei membri, dar după
adăugarea elementului 10 a crescut, iar noua sa lungime va fi 4. Acestei metode i se pot distribui
şi mai mulţi parametri.
Exemplu:
1
2
3
4
var arr = [20,30,40];
var x = arr.unshift(0,2,5,7,10,15);
document.write(arr + "<br/>" + x);<span style="font-size: 14px;"> </span>
Afișarea pe pagină este:
0,2,5,7,10,15,20,30,40
9
Notă:
După adăugarea noilor membri, elementele existente în şir îşi schimbă poziţiile (indecşii). Din
cauza acestei reindexări a tuturor elementelor din şir, metodele shift() şi unshift() sunt mai lente
decât metodele pop() şi push().
Cum convertim şirul în string – join()
Uneori este util să convertim şirul în string. Să presupunem că avem un şir format din câteva
elemente, iar fiecare element reprezintă un cuvânt. Atunci, ca separator de elemente, folosim
spaţiul, iar după executarea metodei obţinem un string nou care reprezintă o propoziţie scrisă
ordonat. Totuşi, ca separator putem să folosim orice string, iar elementele din şir pot fi, dar nu e
obligatoriu să fie cuvinte.
Să analizăm următorul exemplu:
1
2
3
4
var fruits = ["Apple","Orange","Lemon"];
var str = fruits.join(' - ');
document.write(str); <span style="font-size: 14px;"> </span>
82
Afișarea pe pagină este:
Apple – Orange – Lemon
Dacă nu atribuim un parametru metodei, respectiv un separator de elemente, implicit metoda va
folosi virgula ca să separe elementele din noul string.
Să ilustrăm aceasta pe acelaşi exemplu:
1
2
3
4
var fruits = ["Apple","Orange","Lemon"];
var str = fruits.join();
document.write(str);<span style="font-size: 14px;"> </span>
Acum, afișarea va fi:
Apple,Orange,Lemon
Cum convertim string-ul în şir – split()
Metoda split() execută procesul invers în comparație cu metoda join(), respectiv converteşte string-
ul în şir. Ca parametru, trebuie să distribuim semnul după care se va executa metoda de separare a
elementelor.
Să vedem exemplul:
1
2
3
4
var fruits = "Lemon, Apple, Orange";
var arr = fruits.split(',');
document.write(arr[0]);<span style="font-size: 14px;"> </span>
După a doua linie a codului, se creează un nou şir arr care are trei elemente: Lemon, Apple şi
Orange. De aceea, după a treia linie a codului pe pagină va apărea scris:
Lemon
Această metodă poate să accepte şi al doilea parametru, care este opţional. Cu acest parametru, se
stabileşte limita numărului de membri din şir. Deci, metoda va tăia părţi din string şi le va plasa în
şir, până când membrii şirului depăşesc limita sau ajung la finalul string-ului. Să vedem exemplul:
1 var fruits = "Lemon, Apple, Orange";
83
2
3
4
var arr = fruits.split(', ',2);
document.write(arr[2]);<span style="font-size: 14px;"> </span>
Deşi ne-am fi aşteptat ca la indexul 2 (respectiv al treilea membru al şirului) să apară Orange,
aceasta nu se va întâmpla deoarece limit este setat pe două elemente. De aceea, rezultatul de pe
ecran va fi:
Undefined
Notă:
Dacă metodei nu i se distribuie niciun parametru, șirul va fi creat doar cu un element care conține
întregul string.
Cum sortăm şirurile după valorile membrilor – sort()
Metoda sort are mai multe variante. Acum, vom discuta despre varianta sort() principală. Această
metodă sortează membrii şirului după valorile lor, tratându-i ca pe un string, motiv pentru care
trebuie să avem mare grijă când lucrăm cu un şir ale cărui elemente sunt numere, aspect descris în
al doilea exemplu. Acum, să ne ocupăm puţin de primul exemplu, în care se sortează şirul ai cărui
membri sunt de tip string.
Exemplul 1:
1
2
3
4
var arr = ['b','f','a','c','e','d'];
arr.sort();
document.write(arr);<span style="font-size: 14px;"> </span>
Ieşirea pe pagină este: a,b,c,d,e,f.
Exemplul 2:
Afișarea utilizării greşite a metodei sort:
1
2
3
var arr=[3,5,2,6,1,6,0,4,20];
arr.sort();
document.write(arr);<span style="font-size: 14px;"> </span>
84
4
Ieşirea pe pagină este: 0,1,2,20,3,4,5,6,6.
Cu siguranţă, nu acest rezultat este cel pe care am vrut să-l obținem în urma sortării; însă, metoda
valorii le vede ca pe string-uri şi de aceea se ajunge la eroare. Ca să rezolvăm această problemă,
ar trebui să transmitem ca parametru funcţia care se va ocupa de sortarea corectă. Pentru moment
nu e nevoie să înţelegeţi funcţia pe care am scris-o între paranteze, deoarece de funcţii ne vom
ocupa mai târziu, dar este important să reţineţi că în acest fel puteţi rezolva problema sortării
numerelor în şir:
1
2
3
4
5
6
var arr=[3,5,2,6,1,6,0,4,20];
arr.sort(function compareNumbers(a, b) {
return a - b;
});
document.write(arr);<span style="font-size: 14px; text-align:
justify;"> </span>
În acest moment, ieşirea pe pagină este corectă: 0,1,2,3,4,5,6,6,20.
Cum modificăm ordinea elementelor din şir – reverse()
Metoda schimbă ordinea elementelor din şir - ultimul devine primul, iar primul, ultimul:
1
2
3
şir = [1,2,3,4,5,6,7];
document.write(niz.reverse());<span style="font-size: 14px; text-align:
justify;"> </span>
Rezultatul este şirul 7,6,5,4,3,2,1.
Cum utilizăm proprietatea length pentru a tăia şirul
Proprietatea length ne este deja cunoscută. Această proprietate se referă la lungimea şirului, iar cu
metoda sa putem să tăiem șirul.
Să vedem exemplul:
1 var arr = [10,20,30,40,50,60,70,80,90];
85
2
3
4
arr.length = 3;
document.write(arr);<span style="font-size: 14px;"> </span>
Ieşirea pe pagină este:
10,20,30
Cum ștergem un element din şir – delete
Ca să ştergem un element din şir, folosim comanda delete, însă trebuie să ţinem cont că utilizând
această comandă în şir va apărea un spațiu gol pe poziţia unde se afla elementul şters. Să vedem
prezentarea grafică a şirului după ştergerea elementului cu indexul 2:
Imaginea 9.5.
Sintaxa este următoarea:
1
2
3
4
var arr = [10,20,30,40];
delete arr[1];
document.write(arr[1]);<span style="font-size: 14px;"> </span>
Ieşirea pe pagină este:
undefined
Se pune următoarea întrebare: vrem să lăsăm astfel de spații goale în şir? Dacă vrem să înlăturăm
elementul din şir, dar să îi păstrăm structura (lungime şi indecşi), folosim comanda delete. Dacă
după ştergere vrem să reîmpachetăm elementele din şir şi să eliminăm spațiile goale, folosim
metoda splice().
86
Metoda splice()
Una dintre cele mai puternice metode care se poate aplica asupra şirurilor este, cu siguranţă,
metoda splice(), care are opțiunea să şteargă şi să adauge elemente în şir. Spre deosebire de
comanda delete, metoda splice() nu va lăsa spații goale în şir în locurile unde se aflau elementele
care au fost şterse.
Cum ștergem un element din şir, fără să adăugăm altul nou
Să vedem, în primul rând, cum utilizăm metoda de înlăturare a elementului din şir. În acest caz,
metodei trebuie să i se transmită doi parametri. Cu primul parametru, determinăm poziţia din care
va începe tăierea, iar cu al doilea parametru stabilim câţi membri ai şirului vor fi tăiaţi şi eliminaţi
din şir.
Exemplu:
1
2
3
4
var arr = [10,20,30,40];
arr.splice(1,1)
document.write(arr);<span style="font-size: 14px;"> </span>
După executarea acestor linii ale codului de pe pagină, obţinem următoarea ieşire:
10,30,40
Deci, am început tăierea de pe poziţia 1 şi am tăiat un element (cifra 20).
Cum ștergem un element din şir, adăugând noi elemente
După ce ştergem elementel din şir, ne putem opri pe aceeaşi poziţie şi putem adăuga elemente noi.
Notă:
Numărul elementelor introduse nu depinde de numărul celor şterse.
Iată prezentarea grafică:
87
Imaginea 9.6.
Deci, înlăturăm elementul (sau mai multe elemente) de pe o poziţie din şir, iar în locul lui adaugăm
un număr arbitrar de elemente noi. Dacă numărul elementelor noi este diferit de numărul celor
şterse, celelalte elemente din dreapta şirului vor schimba indecşii, pentru a se respecta indexarea
corectă a tuturor elementelor, fără spații goale.
Să analizăm acum un exemplu practic:
1
2
3
4
var arr = [10,20,30,40];
arr.splice(2,1,100,200)
document.write(arr);<span style="font-size: 14px; text-align:
justify;"> </span>
În acest cod, totul este clar, în afară de parametrii funcţiei splice(). Primul parametru este în
continuare poziţia iniţială pentru tăiere. Al doilea parametru este numărul elementului care se taie,
iar ceilaţi parametri sunt elemente numărate, care vor fi eliminate din şir.
Cum adăugăm noi elemente, fără a le înlătura pe cele existente
88
Trebuie să menţionăm că eliminarea elementelor din şir nu este obligatorie în cazul acestei metode,
ci o putem folosi doar pentru a adăuga noi elemente pe o anumită poziţie în şir.
Prezentarea grafică este următoarea:
Imaginea 9.7.
Să vedem exemplul:
1
2
3
4
var arr = [10,20,30,40];
arr.splice(2,0,100,200)
document.write(arr);<span style="font-size: 14px; text-align:
justify;"> </span>
După cum putem vedea, exemplul este aproape identic cu cel precedent, cu excepția faptului că
drept al doilea parametru al metodei am distribuit cifra 0, ceea ce înseamnă că nu am înlăturat
elementele deja existente din şir, ci doar am adăugat niște elemente noi.
Şirurile multidimensionale
Unitate: 10 din 19 00:10:53
89
+Rezumat
Subiectul acestei lecţii constă în utilizarea şirurilor multidimensionale şi aplicarea lor în
JavaScript. Ne vom familiariza cu sintaxa pentru crearea şirurilor multidimensionale, cu sintaxa
pentru furnizarea şi modificarea valorilor elementelor dintr-un şir multidimensional şi vom folosi
buclele pentru a lista şirul.
Şirurile multidimensionale
Un şir poate să conţină toate tipurile de date și prin urmare poate să conţină şi alte şiruri - astfel se
formează şirurile multidimensionale. Aceste şiruri sunt utile pentru lucrul cu datele sub formă
matriceală sau tabelară. Şirurile multidimensionale sunt, de fapt, şiruri de şiruri. De exemplu, să
presupunem că vrem să stocăm date sub formă de tabel care să conţină următoarele coloane: ID,
Prenume, Nume, CNP.
În acest caz, am putea să folosim un şir bidimensional. Accesarea valorilor şirurilor
multidimensionale nu este diferită de cea a valorilor şirurilor obişnuite în JavaScript. Accesăm
elementele folosind, de asemenea, [].
1
2
3
4
5
6
var arr = [];
<br>arr[0]=[1," John","Johnson","1111111111111"];
arr[1]=[2,"Robert","Anderson","2222222222222"];
arr[2]=[3,"Thomas"," Miller","3333333333333"];
document.write(arr[0][1]);<span style="text-align:
justify;"> <br><br></span> Afișează: John .
În lucrul cu şiruri bidimensionale, când trecem prin primul şir trebuie să accesăm elementele
celuilalt şir. Fiecare element al șirului principal este perceput ca un şir special. Putem spune că
noi, în acest exemplu, avem un şir în şir. Menţionând comanda şir [0], mai întâi accesăm elementul
şirului principal. Acest element conţine valorile:
1, John, Johnson, 1111111111111
Această parte se poate percepe ca un şir special. Acum, fiecare element al acestui subşir poate fi
accesat menţionând indexul care reprezintă poziţia unui anumit element în şir. În exemplu am
menţionat indexul 1, ceea ce înseamnă că accesăm al doilea element al acestui subşir, iar elementul
are valoarea John.
Am putea completa șirul şi altfel, în momentul iniţializării:
1 var arr = [[1," John"," Johnson","1111111111111"],
90
2
3
4
[2," Robert"," Anderson","2222222222222"],
[3," Thomas"," Miller","3333333333333"]];
document.write(arr[0][1]);<span style="font-size: 14px; text-align:
justify;"> </span>
Deci, dacă am vrea să obţinem iteraţia prin fiecare nume al acestui tabel, am scrie codul:
1
2
3
4
5
6
var arr = [[1," John"," Johnson","1111111111111"],
[2," Robert"," Anderson","2222222222222"],
[3," Thomas"," Miller","3333333333333"]];
for(i=0;i<arr.length;i++)
document.write(arr[i][1]);<span style="font-size: 14px; text-align:
justify;"> </span>
Ieşirea pe pagină ar arăta astfel:
John John Robert Thomas
Buclele sunt foarte importante pentru afișarea elementelor din şir. Folosind bucla for, putem accesa
fiecare element al şirului, fără să cunoaştem numărul elementelor din şir. Cu proprietatea length a
oricărui şir, obţinem informaţii despre numărul de elemente din şir, stabilind astfel câte iteraţii va
avea bucla for. Concret, în codul menţionat mai sus trecem prin toate elementele şirului principal
şi scriem valoarea celuilalt element (cu indexul 1) al fiecărui subşir.
De asemenea, putem să accesăm toate datele din şir în felul următor:
1
2
3
4
5
6
var arr = [[1," John"," Johnson","1111111111111"],
[2," Robert"," Anderson","2222222222222"],
[3," Thomas"," Miller","3333333333333"]];
for(i=0;i<arr.length;i++)
document.write(arr[i][0] + " " + arr[i][1] + " " + arr[i][2] + " " + arr[i][3] + "<br/>");<span style="font-size: 14px; text-align: justify;"> </span>
Cu acest cod și cu ajutorul buclei for, trecem prin şirul principal şi în cadrul fiecărui element al
şirului principal accesăm valorile care conţin subşiruri.
91
În şirurile bidimensionale, putem adăuga sau modifica valoarea unui anumit element în felul
următor:
1
2
arr[1][1]=" Taylor";
document.write(arr[1][1]);<span style="font-size: 14px; text-align:
justify;"> </span>
Dacă adăugăm acest cod la exemplul precedent, vom vedea că, în loc de numele Robert, am pus
numele Taylor. Cu aceste comenzi, am transmis programului JavaScript ca, în loc de valoarea care
se află pe a doua poziţie a şirului principal (primul index 1), pe poziţia cu indexul 1 al subşirului,
să introducă valoarea Taylor.
Aceste soluţii sunt practice atunci când avem un număr fix de membri ai subşirului (în acest caz,
acestea sunt coloanele tabelului nostru); însă, nu şi dacă vrem să manipulăm date dinamice, a căror
cantitate nu ne este cunoscută în avans. De exemplu, programul care manipulează imaginile pe
care utilizatorul le poate încărca în orice format. În acest caz, ar trebui să lucrăm cu şiruri de
dimensiuni necunocute şi ar trebui să folosim o altă metodă pentru iteraţie prin membrii săi.
De exemplu, matricea care are valori:
1
2
3
1 2 3 4
5 6 7 8
9 0 1 2<span style="font-size: 14px; text-align: justify;"> </span>
Matricea în forma şirului ar arăta astfel:
1
2
3
4
arr = [
[1,2,3,4],
[5,6,7,8],
[9,0,1,2]];<span style="font-size: 14px; text-align: justify;"> </span>
şi ar fi uşor să facem iteraţia prin ea, fiind scoasă din exemplul de mai devreme.
Dar, dacă ne imaginăm că în loc de structura cunoscută, am obţinut un şir variabil, ale cărui date
nu le cunoaştem (decât dacă este şir bidimensional), ar trebui să apelăm o altă tehnică:
1
2
3
arr = [[1,2,3,4],
[5,6,7,8],
[9,0,1,2]];
92
4
5
6
7
8
9
for(n1=0;n1<arr.length;n1++)
{
for(n2=0;n2<arr[n1].length;n2++)
document.write(arr[n1][n2]);
document.write("<br>");
}
Dar nici acest lucru nu este suficient pentru a salva datele legate de o imagine, deoarece pe fiecare
coordonată imaginea posedă un anumit set de date (despre culoare). Având în vedere că acestă
culoare este alcătuită de obicei din trei valori (dacă este vorba de modelul RGB), pentru fiecare
punct va trebui să separăm încă un şir format din trei membri.
Pentru a îndeplini cererea menţionată, trebuie să schimbăm puţin codul de până acum.
În primul rând, să presupunem că şirul pe care l-am obţinut prin decodarea unei imagini arată
astfel:
1
2
3
4
5
arr = [
[[0,0,0],[255,255,255],[0,0,0],[255,255,255]],
[[255,255,255],[0,0,0],[255,255,255],[0,0,0]],
[[0,0,0],[255,255,255],[0,0,0],[255,255,255]]
];
deci, fiecare şir principal este un rând, iar fiecare subşir este într-un rând - un punct.
Pentru iteraţia prin date astfel serializate, am putea să folosim următorul cod:
1
2
3
4
5
6
7
for(n1=0;n1<arr.length;n1++)
{
for(n2=0;n2<arr[n1].length;n2++)
for(n3=0;n3<arr[n1][n2].length;n3++)
document.write(arr[n1][n2][n3] + ", ");
document.write("<br>");
}
93
De ajutor în lucrul cu şirurile multidimensionale este bucla for...in. Această buclă ţine cont de
dimensiune şi poziţiile membrilor cu ocazia iteraţiei.
Folosind bucla for...in, şirul de mai sus ar arăta astfel:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
arr = [
[[0,0,0],[255,255,255],[0,0,0],[255,255,255]],
[[255,255,255],[0,0,0],[255,255,255],[0,0,0]],
[[0,0,0],[255,255,255],[0,0,0],[255,255,255]]
];
for(var L1 in arr)
{
for(var L2 in arr[L1])
{
for(var L3 in arr[L1][L2])
document.write(arr[L1][L2][L3]);
}
document.write("<br/>");
}
După cum am văzut în exemplele de până acum, elementele şirului se accesează pe baza indexului
lor, respectiv a poziţiei lor în şir. De ce mai multe ori este suficient şi foarte practic. În limbajul de
programare astfel de șiruri se numesc şiruri indexate. Să ne imaginăm acum situaţia în care în
aceste şiruri vrem să salvăm date despre utilizatorii prezentaţi în următorul tabel:
id name password tel
1 John John100 0122223333
Tabelul 10.1.
Dacă am fi încercat să punem astfel de date în şirul indexat de până acum, am fi înţeles că trebuie
să renunţăm imediat la nume pentru coloane (id, name, password, tel) şi în loc de asta trebuie să
stabilim o înţelegere privind poziţia pe care vom înregistra datele. În cazul nostru, ar fi logic ca
94
indexul 0 să fie rezervat pentru id, indexul 1 pentru name, indexul 2 pentru password şi indexul 3
pentru tel. Aşadar, şirul ar arăta astfel:
1 var user = [1,'John', 'John100', '0122223333'];<span style="font-size: 14px;
text-align: justify;"> </span>
Atunci când datele sunt stocate astfel în şir, pentru a ajunge la ele trebuie să respectăm cu stricteţe
ordinea datelor introduse şi nu ne putem adresa şirului cu interogarea: „Obţine nume, obţine id...”
etc., așa cum am fi putut face în multe alte limbaje de programare precum Java, C sau PHP care
sprijină utilizarea şirurilor asociative. Totuşi, există o modalitate de rezolvare a problemei
inexistenţei şirurilor clasice asociative în JavaScript, iar despre asta vom discuta în următoarea
lecţie.
Exerciţiu - Listarea şirului prin buclă
Creaţi un şir bidimensional cu un număr arbitrar de elemente. Afișați toate elementele pe pagină
unul sub altul cu ajutorul buclei for (sau for...in).
Rezolvare:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!doctype html>
<html lang="en">
<head>
<title>Array</title>
</head>
<body>
<script>
var arr = [
['apple', 'orange', 'pear'],
['carrots', 'beans', 'peas'],
['cookies', 'cake', 'muffins', 'pie']
];
for (var i=0, len=arr.length; i<len; i++) {
for (var j=0, len2=arr[i].length; j<len2; j++) {
document.write( arr[i][j] + "<br/>");
95
17
18
19
20
21
22
23
}
document.write("<hr/>");
}
</script>
</body>
</html>
Şirurile asociative şi JavaScript
Unitate: 11 din 19 00:11:24
+Rezumat
Limbajul JavaScript se bazează pe obiecte, iar în JavaScript aproape totul este sau poate fi obiect.
De aceea, în această lecţie ne vom ocupa în detaliu de obiecte şi vom vedea cum le putem folosi
în cel mai simplu mod, dar şi în cel mai complex. În acest curs, ne vom ocupa de obiectele pe care
le folosim în calitate de şiruri asociative.
Să ne amintim de tabelul de la finalul lecţiei precedente:
id name password tel
1 John John100 0122223333
Tabelul 11.1.
Să ne amintim şi de faptul că până acum, pentru a putea să furnizăm date fără eroare, trebuia să
creăm un şir indexat cu ordinea stabilită a elementelor din şir. Însă, în acest caz ne-ar fi de mare
ajutor un şir asociativ, respectiv un obiect pe care l-am putea folosi ca şir asociativ.
Să ne imaginăm că numele coloanelor din tabele sunt chei, cu ajutorul cărora putem să deschidem
casete.
Să privim următoarea ilustraţie:
96
Imaginea 11.1.
În acest caz, şirul nostru asociativ de chei ar fi: id, name, password şi tel, în timp ce cutiile,
respectiv valorile: 1, John, John100 şi 0122223333.
Să vedem acum în sintaxă cum putem accesa valorile pe baza acestor chei.
Mai întâi, menţionăm numele şirului asociativ (sau obiect) şi între paranteze pătrate punem
valoarea cheii pe care o căutăm:
1 arr['cheie']<span style="font-size: 14px; text-align: justify;"> </span>
Acum, am putea să creăm variabila căreia îi va fi atribuită valoarea casetei indicată de o anumită
cheie. Să considerăm, pentru exemplul nostru, variabila x, iar cheia name:
1 var x = arr['name'];<span style="font-size: 14px; text-align:
justify;"> </span>
După această linie de cod, variabila x ar avea valoarea John, desigur, cu condiţia să existe şirul
asociativ arr. Să analizăm acum cum am putea să creăm un astfel de şir.
Primul mod
Cel mai simplu mod de creare a obiectului (a se citi şir asociativ) este utilizarea parantezelor
acolade:
97
1 var arr = {};<span style="font-size: 14px;"> </span>
În acest fel, am creat un obiect gol, pe care îl vom folosi ca şir asociativ.
Al doilea mod
Obiectele se pot crea şi cu ajutorul cuvântului-cheie new:
1 var arr = new Object();<span style="font-size: 14px;"> </span>
Pentru moment însă vom evita o astfel de sintaxă şi pentru următoarele noastre exemple, vom
folosi parantezele acolade.
Însă, obiectul nostru, pe care planificăm să-l folosim ca şir asociativ, nu are în continuare niciun
element, de aceea aici vom explica cum să adăugăm elemente noi în şir. Pentru început, trebuie să
atragem atenţia asupra terminologiei. De fapt, încet încet ne obişnuim să numim astfel obiectul pe
care îl folosim ca şir asociativ. Același lucru se întâmplă şi cu cheile din şirul asociativ. Când
utilizăm astfel de identificatori în obiectul care se foloseşte drept şir asociativ, le numim chei, iar
când folosim aceşti identificatori în obiecte cu un alt scop, le numim proprietăţile obiectului
respectiv. În această lecţie, nu ne vom ocupa foarte mult de folosirea obiectelor în alte contexte, ci
doar în contextul şirului asociativ și de aceea aceste proprietăţi se vor numi chei.
Să adăugăm acum cheile şi valorile şirului nostru asociativ. Acest lucru se poate face în două
moduri.
Primul mod
Modul este foarte asemănător cu cel cu care v-aţi familiarizat în lecţiile precedente. Până acum,
am folosit paranteze pătrate pentru a atribui şirului o nouă valoare pe o anumită poziţie, dar
întotdeauna am folosit indexurile. În cazul şirurilor asociative, sintaxa este aceeaşi, dar în loc de
index folosim string-urile, cărora le identificăm cheia.
Să vedem pe un exemplu cum putem crea un şir asociativ în tabelul nostru:
1
2
3
4
5
var user = {};
user['id'] = 1;
user['name'] = 'John';
user['password'] = 'John100';
user['tel'] = '0122223333';
98
Al doilea mod
Pe lângă parantezele pătrate, putem folosi şi aşa-numita notaţie dot:
1
2
3
4
5
var user = {};
user.id = 1;
user.name = 'John';
user.password = 'John100';
user.tel = '0122223333';
Notă:
Această notaţie nu va funcţiona dacă numele cheii începe cu un număr.
Exemplu:
1 user.3d = "YES";<span style="color: #ff0000; font-size: 15.399998664856px;
text-align: justify;"> </span>
Înregistrarea va provoca o eroare.
Folosind diferite adnotări, am creat un şir asociativ cu câteva elemente; însă, în ambele moduri am
creat mai întâi un obiect gol, după care am accesat o singură definire a cheilor şi a valorilor lor.
Toate acestea se pot face şi într-o singură linie de cod, în felul următor:
1 var user = {id:1, name:'John', password:'John100', tel:'0122223333'};<span
style="font-size: 14px; text-align: justify;"> </span>
Observaţi că am separat cheile de valoare cu semnul : (două puncte), în timp ce pentru a separa
elementele am folosit virgula.
Am fi obţinut același efect şi în felul următor, dar înregistrarea ar fi fost mai transparentă:
1
2
3
4
var user = {
id:1,
name:'John',
password:'John100',
tel:'0122223333'
99
5
6
};
Notă:
Observaţi că după ultimul element nu există virgulă.
După cum la şirurile indexate elementele pot fi de diferite tipuri, tot așa, la şirurile asociative
valorile pot fi diferite. Până acum, pentru valorile elementelor din şir am folosit numere şi string-
uri, dar putem să folosim şi valori boolean, alte şiruri, funcţii sau chiar alte obiecte.
Să vedem într-un exemplu cum putem crea un şir asociativ într-un şir asociativ şi cum îl accesăm:
1
2
3
4
5
6
7
8
9
10
11
var user = {
id:1,
name:'John',
password:'John100',
tel: {
personal:'0111222',
business:'1222333'
}
};
document.write(user['tel']['business']);
Deci, folosim aceeaşi sintaxă pentru ca pe poziţia valorii pentru cheie din şirul extern să creăm un
şir intern sau, cu alte cuvinte, pe poziţia proprietăţii obiectului extern, să creăm un obiect intern.
Cu ultima linie a codului, accesăm valoarea internă şi o scriem în document. Când accesăm
valoarea, ţinem cont de traiectorie.
Să analizăm următoarea ilustraţie:
100
Imaginea 11.2.
După cum puteți vedea, mai întâi menţionăm identificatorul pentru şir (respectiv obiect - user),
apoi între paranteze pătrate definim accesul la identificatorul tel, după care, în final, ajungem la
ultimul nivel şi alegem identificatorul business, pentru a obţine numărul de telefon corespunzător.
Am obţine acelaşi efect şi folosind adnotarea dot:
1 user.tel.business<span style="font-size: 14px;"> </span>
sau combinând aceste adnotări:
1
2
Primul mod: user['tel'].business
Al doilea mod: user.tel['business']<br><br><span style="font-size:
14px;"> </span>
Cheia inexistentă – undefined
Dacă încercăm să obţinem valoarea pentru cheia care nu este definită în şir, nu se va produce o
eroare și în loc de aceasta va fi returnată valoarea undefined.
101
Exemplu:
1
2
3
4
5
6
7
8
9
10
11
var user = {
id:1,
name:'John',
password:'John100',
tel: {
personal:'0111222',
business:'1222333'
}
};
document.write(user['age']);
1
Pe pagină, vom obţine ca rezultat: undefined.
Un astfel de comportament se poate folosi pentru crearea expresiilor, pe care le vom folosi la
testarea şirului, atunci când vrem să confirmăm dacă cheia există în şir sau nu.
Exemplu:
1
2
3
4
5
6
7
8
9
10
var user = {
id:1,
name:'John',
password:'John100',
tel: {
personal:'0111222',
business:'1222333'
}
};
if (user.name !== undefined) {
document.write(" I've got a name! ")
102
11
12
}
Dacă şirul dintre paranteze este corect (true), respectiv dacă cheia name există, condiţia va fi
îndeplinită şi se va executa blocul de cod.
Listarea şirurilor asociative
Într-una din lecţiile precedente, am explicat cum funcţionează bucla for...in. Acum, vom prezenta
cum se poate folosi aceasta pentru a lista şirurile asociative. Să ne amintim că, la fiecare iteraţie,
această buclă returnează indexul la care a ajuns iteraţia în acel moment. Deoarece la şirurile
asociative nu avem indexuri, în loc de ele folosim chei, astfel încât la fiecare iteraţie această buclă
să returneze cheia pe care a găsit-o. Aceasta înseamnă că vom avea atâtea iteraţii câte chei are şirul
asociativ.
Exemplu:
1
2
3
4
5
6
7
8
var user = {
id:1,
name:'John',
password:'John100',
};
for(var i in user){
document.write(user[i] + "<br/>");
}
Deoarece şirul nostru asociativ are trei elemente, şi bucla va avea trei iteraţii. În prima iteraţie,
variabila i va avea valoarea id, în a doua iteraţie i va avea valoarea name, iar în ultima, password.
Din cauza acestui tip de comportament, în corpul buclei trebuie să menţionăm numele şirului
(user), apoi între paranteze pătrate punem variabila i, pentru a obţine scrierea tuturor membrilor.
Notă:
Nu este garantat că toate browser-ele vor trece prin şir în aceeaşi ordine. Majoritatea vor lista mai
întâi cheile care conţin numărul, după care cheile care conţin caractere literale şi altele. Pe de altă
parte, versiunile mai vechi de Internet Explorer (IE<9) vor lista cheile în ordinea în care sunt scrise
în cod.
103
Utilizarea de bază a funcțiilor definite de
utilizator
Unitate: 12 din 19 00:23:07
+Rezumat
În această lecţie ne vom familiariza cu noţiunea de funcţie în programare. Deşi, în afară de lecția
introductivă, până acum nu am abordat noţiunea de funcţie, ea a făcut parte din activitatea noastră
de la bun început. Aceasta se datorează faptului că majoritatea comenzilor pe care le-am folosit
sunt, de fapt, funcţii.
După următoarea descriere, vom recunoaşte uşor când am folosit până acum funcţiile, deoarece
vom vorbi despre caracteristicile lor, respectiv forma lor caracteristică. În primul rând, să explicăm
ce înseamnă o funcţie, în general.
Funcţia este o structură de programare care, pe baza anumitor parametri determinaţi, sau fără ei,
efectuează un serviciu. În continuare, funcţia poate avea o valoare de returnare pe care o va returna,
dar poate exista şi fără valoare de returnare.
Argumentele pentru utilizarea funcţiilor în programare sunt multiple. Dar principalele avantaje ale
funcţiei sunt:
încapsularea (gruparea unei funcţionalităţi);
reducerea redundanţei codului;
viteza de codare;
portabilitatea.
Funcţiile ocupă un rol-cheie şi în programarea modernă orientată pe obiect deoarece, practic,
funcţionalitatea completă a claselor (care reprezintă bazele programării orientate pe obiect) este
stocată tocmai în metodele acestor clase. Metodele claselor sunt cele mai obişnuite funcţii.
Funcţiile sunt un instrument foarte util fără nicio legătură cu OOP. În JavaScript, o funcţie poate
apela altă funcţie.
JavaScript nu funcţionează după modelul clasic orientat pe obiect, ci după aşa-numitul model
obiectual bazat pe prototip, dar regulile sunt destul de similare şi, înţelegând unul din aceste două
modele, îl putem înțelege și realiza ușor și pe celălalt.
Într-un program se utilizează foarte frecvent același bloc de cod. Dacă nu ar exista funcţiile, atunci,
în cel mai bun caz, ar trebui să copiem codul în fiecare loc unde avem de el.
Pentru a descrie opțiunile oferite de funcţiile în acţiune, să ne imaginăm următoarea situaţie:
104
O companie care produce role de aluminiu vrea să creeze o aplicaţie JavaScript care, printre altele,
trebuie să calculeze masa rolelor de aluminiu. Dat fiind că masa specifică a rolei de aluminiu este
în jur de 2700 kg pe metru cub, iar rolele au formă cilindrică, folosim următoarea logică:
masa_rolei = volumul_rolei_în_metri_cubi x 2700
Pentru a calcula volumul rolei, folosim formula volumului cilindrului:
volumul_rolei_în_metri_cubi = baza înălţimii x
Baza cilindrului se calculează ca suprafaţa cercului, respectiv: .
Astfel, formula finală ar fi:
.
Imaginea 12.1.
Acum, cu această formulă putem să calculăm volumul oricărei role. Să presupunem că cerința dvs.
în acest moment este să calculați masa a trei role diferite şi să afișați rezultatul într-o fereastră de
notificare:
Prima rolă: raza = 0,3 m, înălţimea = 1m;
A doua rolă: raza = 0,5 m, înălţimea = 0,7 m;
A treia rolă: raza = 0,8 m, înălţimea = 1,5 m.
Fără ajutorul funcţiilor, nu puteam să scriem codul astfel:
105
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var r = 0.3; var h = 1; var m1 = r*r * 3.14 * h * 2700; alert("A roll of aluminum foil has a mass of " + m1 + " kg.");
r = 0.5; h = 0.7; var m2 = r*r * 3.14 * h * 2700; alert("A roll of aluminum foil has a mass of " + m2 + " kg."); r = 0.8; h = 1.5; var m3 = r*r * 3.14 * h * 2700; alert("A roll of aluminum foil has a mass of " + m3 + " kg.");<span style="font-size: 14px; text-align: justify;"> </span>
Să analizăm, mai întâi, codul scris. La început, definim variabilele r şi h. Apoi, definim
variabila m1, care reprezintă rezultatul calculului. La final, apelăm metoda alert(), căreia îi
atribuim acest rezultat pentru a-l afișa utilizatorului. Acest procedeu se repetă pentru fiecare rolă.
Știm că în programare se evită repetarea aceluiaşi tip de linii, însă vedem că aici regula nu se
respectă, deoarece aceeaşi formulă se scrie din nou şi din nou pentru fiecare exemplu. De
asemenea, şi linia de cod care reprezintă alert este aproape aceeaşi în toate cele trei locuri.
Se pune întrebarea cum să evităm repetarea acestor linii de cod şi cum să înlăturăm posibilitatea
ca o nouă eroare să apară în urma repetării. Răspunsul stă în funcţii. Ne putem imagina funcțiile
ca pe niște maşini care aşteaptă să introducem în ele o materie primă pe care acestea o vor prelucra
şi o vor transforma într-un produs finit. În cazul nostru, materiile prime sunt valorile pentru r şi h
și produsul alert() care scrie mesajul:
Imaginea 12.2.
Avem valorile pentru r şi h, iar funcţia alert() ne este cunoscută, ceea ce înseamnă că pentru a crea
funcţia trebuie analizat restul. De aceea, să vedem un exemplu pe care îl vom analiza în detaliu:
1
2
function alu_foil(r,h) { var m = r*r * 3.14 * h * 2700;
106
3
4
alert("A roll of aluminum foil has a mass of " + m + " kg."); }
Primul pas către crearea funcţiei este menţionarea cuvântului-cheie function. Pentru a atribui
funcţiei numele după acest cuvânt-cheie, scriem identificatorul pentru funcţie după aceleaşi reguli
cu care am definit identificatorul pentru variabilă. Apoi, după cum puteţi vedea, punem valorile pe
care le primeşte funcţia şi pe care le poate folosi pentru a afișa un rezultat între paranteze obişnuite.
După cum vedem şi în ilustraţie, funcţia noastră trebuie să accepte valorile pentru raza şi înălţimea
rolei.
Notă:
Funcţia poate fi creată, aşadar nu are nevoie de parametrii necesari pentru a funcţiona corect, dar
totuşi trebuie să fie setate paranteze deschise şi închise după numele funcţiei.
După ce am definit parametrii de intrare, accesăm definirea corpului funcţiei. Corpul funcţiei este
un segment de cod care va fi executat atunci când apelează o funcţie, iar această parte a codului se
scrie între paranteze acolade. Vom folosi exact acest spaţiu pentru a scrie formula şi linia de cod
care va afișa rezultatul. Observaţi că în corpul funcţiei folosim variabile care sunt puse între
paranteze obişnuite. Aceste variabile se numesc parametrii funcţiei sau argumente, iar funcţia
noastră aşteaptă să fie creați aceşti parametri, respectiv să-i fie distribuiți, pentru a putea să
returneze un rezultat adecvat. Prima linie a codului din corpul funcţiei noastre reprezintă definirea
variabilei m care primeşte valoarea expresiei din partea dreaptă. La final, definim şi a doua linie
de cod în corpul funcţiei, care afișează caseta alert/de notificare şi scrie rezultatul.
Notă:
Corpul funcţiei trebuie pus între paranteze acolade. De exemplu, următoarea funcţie nu este scrisă
corect:
1 function myFunction(a,b) return a+b;
Am finalizat crearea funcţiei, însă, dacă am scrie pe pagină un astfel de cod:
1
2
3
4
5
6
7
var r = 0.3; var h = 1; function alu_foil(r,h) { var m = r*r * 3.14 * h * 2700; alert("A roll of aluminum foil has a mass of " + m + " kg."); }
nu s-ar întâmpla nimic, deoarece nu am indicat nicăieri că trebuie executată funcţia. Deci, astfel
de mecanisme (funcţii) nu se vor executa singure, ci la fel ca şi în cazul unor mașini adevărate,
acestea vor aştepta să fie activate şi, eventual, să introducem în ele materia primă cu care vor
funcționa. Ilustrate arată astfel:
107
Imaginea 12.3.
Deci, avem variabilele, avem şi mecanismul care poate lucra cu aceste variabile, dar, pentru că nu
am activat maşina şi nici nu i-am atribuit variabilele, nu primim nici rezultatele (alert()). De aceea,
acum, după ce am definit variabilele r şi h, vom apela funcţia şi îi vom atribui aceşti parametri:
1
2
3
4
5
6
7
8
9
var r = 0.3; var h = 1;
alu_foil(r,h); function alu_foil(r,h) { var m = r*r * 3.14 * h * 2700; alert("A roll of aluminum foil has a mass of " + m + " kg."); }
Apelăm funcţia prin simpla menţionare a numelui ei, după care între paranteze punem valori pentru
parametrii solicitaţi de funcţie. Dacă pornim acest cod, vom obţine ieşirea pe ecran. De asemenea,
când apelăm funcţia putem să folosim şi literali în loc de variabile.
Exemplu:
1
2
3
4
5
6
alu_foil(0.3,1); function alu_foil(r,h) { var m = r*r * 3.14 * h * 2700; alert("A roll of aluminum foil has a mass of " + m + " kg."); }
Să folosim acum funcţia şi pentru celelalte două calcule din primul exemplu:
108
1
2
3
4
5
6
7
8
alu_foil(0.3,1); alu_foil(0.5,0.7); alu_foil(0.8,1.5); function alu_foil(r,h) { var m = r*r * 3.14 * h * 2700; alert("A roll of aluminum foil has a mass of " + m + " kg."); }
Așadar, dacă folosim funcţia, pentru calcul avem nevoie de o linie de cod, în timp ce, dacă nu o
folosim, avem nevoie de mai multe linii de cod. De asemenea, acum suntem siguri că nu vom
provoca o eroare în urma copierii frecvente a codului. Un alt beneficiu important al utilizării
funcţiilor este şi faptul că putem să efectuăm uşor modificările. De exemplu, dacă am vrea să
corectăm masa specifică pentru aluminiu, putem face aceasta într-un singur loc - în funcţie, în timp
ce în exemplul fără funcţie ar trebui să facem corecţia în fiecare loc în care această valoare apare.
Dacă lucrăm cu mai multe intrări, cazul din exemplu, aceasta nu pare o problemă prea mare, dar
dacă am lucra cu câteva mii de introduceri, atunci utilizarea funcţiilor reprezintă o soluţie mult mai
bună.
Cum definim valoarea pe care o returnează funcţia – return
Funcţia pe care tocmai am creat-o acceptă nişte parametri, face calculul, după care execută o
acţiune (alert), dar nu returnează nimic ca rezultat în locul de unde este apelată.
Notă:
Dacă facem o analiză mai amănunţită a designului limbajului de programare, observăm că funcţiile
returnează totuși întotdeauna o valoare. Dacă nu este definită o altă valoare pe care funcția să o
returneze, aceasta va returna singură valoarea primitivă undefined. Însă, pentru cerințele cursului
nostru, această valoare este lipsită de importanţă ca dimensiune, ca să zicem aşa: „Funcţia nu
returnează nimic”.
Când lipsa funcţiei precedente constă în faptul că returnează o notificare utilizatorului, dar în
continuare nu ne permite să ne ocupăm matematic de rezultat, atunci avem nevoie de comanda
return. Această comandă întrerupe automat executarea blocului de cod în funcţie şi, în locul din
care a fost apelată funcţia, trimite valoarea menţionată după comanda return.
Iată reprezentarea grafică:
109
Imaginea 12.4.
Acesta ar fi cazul în care funcţia calculează o valoare pe baza parametrilor distribuiţi, după care
rezultatul obţinut este returnat în locul din care a fost apelată funcţia. Aceasta înseamnă că, după
executarea blocului de cod în corpul funcţiei, variabila x are valoarea numerică care reprezintă
masa rolei de aluminiu, a cărei rază este de 0,8 m și înălţime de 1,5 m.
Să vedem acum sintaxa:
1
2
3
4
5
6
7
var x = alu_foil(0.8,1.5); alert(x); function alu_foil(r,h) { var m = r*r * 3.14 * h * 2700; return m; }
După cum vedeţi, în loc ca funcţia să scrie singură valoarea variabilei, aceasta se distribuie în locul
din care a fost apelată, astfel încât după comanda return am setat variabila care a fost calculată
înainte.
Notă: Codul scris după linia return nu va fi executat. Să vedem exemplul:
1 var x = alu_foil(0.8,1.5); alert(x);
110
2
3
4
5
6
7
8
function alu_foil(r,h) { var m = r*r * 3.14 * h * 2700; return m; alert("Not work."); }
alert() setat după return m nu va fi afișat, deoarece funcţia și-a încheiat activitatea imediat ce a
dat de expresia return.
Totuşi, funcţia poate executa o acţiune şi returna rezultatul în acelaşi timp. Să prezentăm grafic
lecţia precedentă, care are acum funcţionalitatea suplimentară de a afișa mesajul, apoi de a returna
valoarea în locul din care a fost apelată.
Imaginea 12.5.
Să analizăm sintaxa acestui exemplu:
1
2
3
4
5
6
7
8
var x = alu_foil(0.8,1.5); alert(x); function alu_foil(r,h) { var m = r*r * 3.14 * h * 2700; alert("A roll of aluminum foil has a mass of " + m + " kg."); return m; }
Înainte de comanda return, am apelat funcţia alert() care afișează pop-up-ul ilustrat în dreapta.
Apoi, funcţia merge mai departe şi găseşte comanda return, unde se şi execută, returnând astfel
valoarea pentru m în variabila x. Pentru a dovedi că toate acestea au avut loc, scriem alert(x) în a
doua linie de cod, ceea ce duce la apariţia a încă unei ferestre pop-up.
111
Scrierea funcţiilor care returnează rezultatul în loc să-l afișeze poate are mai multe utilizări. Primul
avantaj constă în faptul că rezultatul se poate scrie în mai multe feluri, deoarece nu este determinat
de funcţie. De aceea, aceeaşi funcţie se poate folosi în diferite locuri. De asemenea, când funcţia
returnează rezultatul, acesta poate fi manipulat.
Să analizăm următoarea cerere: Cu ajutorul funcţiei alu_foil(), trebuie să calculăm volumul a trei
role, să adunăm aceste volume şi să scriem rezultatul pe pagină.
Rezolvare:
1
2
3
4
5
6
7
var total = alu_foil(0.3,1) + alu_foil(0.5,0.7) + alu_foil(0.8,1.5); document.write(total + "kg");
function alu_foil(r,h) { var m = r*r * 3.14 * h * 2700; return m; }
Tipurile de funcţii
JavaScript are două tipuri de funcţii: definite de utilizator şi interne (încorporate). Acestea fac parte
din limbajul JavaScript. Toate funcţiile pe care programatorul le scrie în timpul procesului de
creare a aplicaţiei se numesc funcţii definite de utilizator. De exemplu, funcţia alu_foil(), pe care
am creat-o mai devreme, este un exemplu de funcţie definită de utilizator. Aceste funcţii sunt create
de programator pentru nevoile speciale ale aplicaţiei sale, atunci când nu există o funcţie
încorporată care să poată face acest serviciu.
Am menţionat funcţiile încorporate. În această categorie intră toate acele funcţii (metode) care se
află deja în JavaScript şi pe care le putem folosi imediat. Despre aceste funcţii, vom discuta în
lecţia următoare.
Unde poziţionăm funcţiilor
Funcţia poate fi scrisă oriunde în cod, dar practica obişnuită este ca toate funcţiile să se scrie la
începutul codului, înaintea celorlalte comenzi. De asemenea, funcţia poate fi scrisă şi într-un fişier
special. Atunci, acest fişier trebuie inclus în fiecare pagină care îi va folosi funcţiile. De asemenea,
funcţiile pot fi apelate din orice parte a codului JavaScript. Scrierea funcţiilor într-un fişier special
poate fi utilă când vreţi să folosiţi aceleaşi funcţii în mai multe locaţii (diferite fişiere HTML),
când le introduceţi în cod în loc să le copiați de fiecare dată, dar totuşi nu trebuie să exageraţi cu
numărul de fişiere externe care se încarcă, deoarece aceasta poate influenţa negativ performanţele
aplicaţiei dvs.
Domeniul de aplicare a funcţiei – function scope
112
În JavaScript, funcțiile au propriul domeniu de aplicare sau function scope. Acest domeniu se
referă la variabilele care sunt declarate în afara sau în cadrul funcţiei. De fapt, întotdeauna când
creaţi o variabilă, aceasta devine proprietatea unui obiect. Variabilele pe care le-am declarat până
atunci, în general, au devenit proprietate a obiectului global. Variabilele astfel create se mai
numesc şi variabile globale, ceea ce înseamnă că pot fi accesate din orice parte a aplicaţiei. Însă,
dacă creăm variabila în cadrul funcţiei cu ajutorul cuvântului-cheie var, aceasta va deveni variabilă
locală, pe care o putem accesa doar din funcţia în care este creată sau din funcţiile care sunt create
în cadrul funcţiei respective. Această relaţie cu domeniul de aplicare se numeşte scope chain.
Să vedem următorul exemplu:
1
2
3
4
5
function myFunction() { var X = 4; }
alert(X);
Am creat funcţia myFunction() şi în corpul acestei funcţii am definit variabila X, a cărei valoare
este 4. Apoi, în afara acestei funcţii încercăm să accesăm variabila X şi să o afișăm pe ecran. Însă,
nu se întâmplă nimic deoarece variabila X nu este definită în obiectul global, ci aparţine domeniului
local de aplicare a funcţiei myFunction().
Să vedem prezentarea grafică:
Imaginea 12.6.
113
Funcţia noastră alert(X) încearcă să găsească variabila, dar nu va intra în domeniul de aplicare a
funcţiei. Deşi variabila X a fost definită în corpul funcţiei, aceasta aparţine domeniului local de
aplicare şi nu este validă din exterior. Nu vă lăsaţi induşi în eroare de faptul că funcţia nu este
apelată, deoarece, chiar dacă ar fi, în acest caz variabila X nu ar fi variabilă, deoarece este locală.
Exemplu:
1
2
3
4
5
6
function myFunction() { var X = 4; }
myFunction(); alert(X);
Când executăm codul, vedem că nu avem niciun rezultat deoarece, deşi am apelat funcţia, variabila
X rămâne în continuare locală.
Pe de altă parte, scenariul invers este permis. Din funcţie, putem accesa toate variabilele globale.
Să vedem prezentarea grafică:
Imaginea 12.7.
114
O astfel de traiectorie este posibilă. Să vedem acum aceasta în cod:
1
2
3
4
5
var X = 10; function myFunction() { alert(X) } myFunction();
Mai întâi, am definit variabila X în afara oricărei funcţii şi aceasta a devenit globală, după care, în
cadrul funcţiei, cu ajutorul metodei alert() am încercat să accesăm variabila X şi am reuşit,
deoarece o astfel de direcţie de deplasare este posibilă.
Monitorizarea acestui lanţ este posibilă şi pentru funcţiile din cadrul funcţiilor (funcţii imbricate).
Să vedem prezentarea grafică:
Imaginea 12.8.
115
Să vedem acum sintaxa acestei prezentări:
1
2
3
4
5
6
7
8
9
10
var X = 10; function myFunction() { var Y = 20; myFunction2(); function myFunction2(){ alert(X); alert(Y); } } myFunction();
În prima linie de cod, declarăm variabila globală X, care are valoarea 10. În cadrul funcţiei
myFunction, se declară variabila X şi aceasta devine variabila locală a funcţiei. Apoi, creăm o
funcţie nouă, myFunction2, care are propriul domeniu de aplicare, dar poate accesa toate domeniile
de aplicare de deasupra sa. Deci, poate accesa şi variabile care au fost create în funcţia myFunction,
dar şi variabile globale. De aceea, ca rezultat apar două ferestre pop-up.
Deoarece variabilele globale şi locale nu sunt aceleaşi variabile, se poate întâmpla să aibă acelaşi
nume (identificator). Când verificăm domeniul de aplicare, vom lua în considerare prima variabilă
întâlnită.
Să vedem prezentarea grafică:
116
Imaginea 12.9.
După cum vedeţi, avem variabila globală X şi variabila locală cu acelaşi nume în domeniul de
aplicare a funcţiei myFunction. Când din funcţia imbricată myFunction2 încercăm să accesăm
variabila X, aceasta este căutată mai întâi în corpul funcţiei myFunction2. Când se confirmă că
variabila X nu există aici, se trece la legătura de deasupra domeniului de aplicare a funcţiei
myFunction şi aici are loc verificarea. Dată fiind variabila X, aici verificarea nu se mai face, ci
această valoare este returnată ca parametru al funcţiei alert. În caz că variabila X nu se găseşte nici
în domeniul de aplicare a funcţiei myFunction, are loc scenariul marcat acum cu linia roşie.
Utilizarea avansată a funcţiilor
Unitate: 13 din 19 00:11:16
+Rezumat
117
În lecţia precedentă, am abordat o parte semnificativă din JavaScript referitoare la crearea și
utilizarea funcţiilor. Acum, vom trata câteva unităţi care sunt necesare pentru lucrul puțin mai
avansat cu funcţiile. Vom afla cum putem defini variabilele globale din corpul funcţiei, cum putem
defini valorile implicite pentru parametrii care nu sunt distribuiţi, cum funcţionează funcţiile
anonime, cum putem apela automat funcţia după încărcare. De asemenea, ne vom familiariza şi cu
funcţiile recursive. La final, vom prezenta câteva funcţii încorporate folosite cel mai des.
Cum definim variabila globală din corpul funcţiei
Am spus că variabilele formate în corpul funcţiei sunt vizibile doar acestei funcţii şi tuturor
funcţiilor care se află în corpul acestei funcţii. Însă, se pune întrebarea cum am putea să definim o
variabilă din corpul funcţiei care să fie vizibilă la nivel global. Cu alte cuvinte, creăm variabila
globală din domeniul local de valabilitate a funcţiei.
Să vedem prezentarea grafică:
Imaginea 13.1.
După cum se vede din prezentarea grafică, variabila din corpul funcţiei se poate defini în două
moduri: folosind cuvântul-cheie var sau fără el. Dacă în corpul funcţiei folosim cuvântul-cheie
var, variabila va fi creată ca variabilă locală; pe de altă parte, dacă nu se foloseşte cuvântul-cheie,
funcţia devine globală în mod automat.
Să vedem acum exemplul aplicat pe un cod:
118
1
2
3
4
5
6
function myFunction(){
var X = 10;
Y = 20;
}
myFunction();
document.write(Y);<span style="font-size: 14px; text-align:
justify;"> </span>
În primul rând, am creat funcţia care defineşte două variabile X şi Y. Deoarece în faţa
variabilei X am pus cuvântul-cheie var, aceasta este creată în funcţia locală myFunction. În faţa
variabilei Y, nu avem cuvântul-cheie var, deci aceasta este creată automat ca variabilă globală şi
este vizibilă în afara funcţiei myFunction.
Notă:
Dacă nu apelăm funcţia (myFunction(); – a cincea linie a codului), variabila Y nu poate fi accesată
deoarece funcţia nu a efectuat şi variabilele X şi Y, oricum ar fi ele, și nu au fost create. Deci,
următorul exemplu nu ar funcţiona:
1
2
3
4
5
6
function myFunction(){
var X = 10;
Y = 20;
}
document.write(Y);<span style="font-size: 14px; text-align:
justify;"> </span>
Trebuie să avem grijă atunci când creăm variabile globale. De fapt, fiecare variabilă care este
creată ca şi globală devine proprietatea obiectului global. Este clar că fiecare proprietate trebuie să
aibă un nume (identificator), aşadar, dacă creaţi încontinuu variabile globale, chiar şi atunci când
acestea ar trebui să fie locale, creşteţi riscul de confruntare a variabilelor cu acelaşi nume. Sfatul
nostru este: creaţi întotdeauna variabile cu ajutorul cuvântului-cheie var și doar atunci când sunteţi
siguri că vreţi să creaţi o variabilă globală, nu folosiți cuvântul-cheie var.
Cum definim valorile implicite pentru parametrii funcţiei
După cum ştim deja, funcţia poate, dar nu trebuie, să aştepte parametrii care i se distribuie. Cu
funcţiile pe care le-am realizat până acum, am distribuit întotdeauna parametrii aşteptaţi în ordine.
Însă, dacă am apela funcţia, fără să-i distribuim parametrii de care are nevoie, apare o eroare. Se
119
pune întrebarea cum să evităm eroarea şi să învăţăm funcţia să acționeze singură, dacă nu-i sunt
distribuiţi parametrii necesari. Răspunsul stă în definirea valorilor implicite pentru parametrii
funcţiei. Valorile implicite vor fi luate în considerare doar atunci când parametrii aşteptaţi nu au
fost distribuiţi.
Să ne imaginăm următoarea cerere de utilizator. Trebuie creată o funcţie care să calculeze volumul
pătratului. Funcţia aşteaptă să i se transmită lungimile laturilor pătratului. Dacă lungimea unei
laturi nu-i este transmisă, ia valoarea implicită 1.
Sintaxa rezolvării este:
1
2
3
4
5
6
7
8
9
function funcC(a,b,c){
if (a === undefined) a = 1;
if (b === undefined) b = 1;
if (c === undefined) c = 1;
var V = a*b*c;
return V;
}
document.write(funcC(3,5));<span style="font-size: 14px; text-align:
justify;"> </span>
Deja de la prima vedere putem concluziona că rezolvarea este destul de simplă. Pentru fiecare
argument al funcţiei, are loc o testare. Dacă valoarea argumentului este undefined, înseamnă că
acest argument este omis când apelăm funcţia, aşadar îi putem atribui valoarea implicită. În cazul
nostru, aceasta este valoarea numărului 1. Când apelăm funcţia de pe ultima linie a codului, omitem
al treilea argument (pagina c), motiv pentru care acestuia i se atribuie valoarea implicită 1,
rezultatul funcţiei fiind 15.
Acesta este doar unul dintre modurile în care putem defini valorile implicite ale parametrului, ele
fiind mai multe. Observaţi următoarele propuneri de soluţii.
Rezolvarea 2:
1
2
3
4
5
function funcC(a,b,c){
var s1 = a || 1;
var s2 = b || 1;
var s3 = c || 1;
var V = s1*s2*s3;
120
6
7
8
9
return V;
}
document.write(funcC(3,5));<span style="font-size: 14px; text-align:
justify;"> </span>
Rezolvarea 3:
1
2
3
4
5
6
7
8
function funcC(a,b,c){
if(typeof(a)==='undefined') a = 1;
if(typeof(b)==='undefined') b = 1;
if(typeof(c)==='undefined') c = 1;
var V = a*b*c;
return V;
}
<br>document.write(funcC(3,5));<span style="font-size: 14px; text-align:
justify;"> </span>
Observaţi că logica este aceeaşi, numai sintaxa diferă.
Notă:
Există o tehnologie experimentală care încă nu a fost implementată în toate browser-ele, dar este
susținută de Firefox (Gecko) de la sfârşitul lui 2012 și care se referă tocmai la setarea valorilor
implicite ale argumentelor funcţiei.
Sintaxa arată astfel:
1
2
3
4
5
function funcC(a = 1,b = 1,c = 1){
var V = a*b*c;
return V;
}
<br>document.write(funcC(3,5));<span style="font-size: 14px; text-align:
justify;"> </span>
Dacă aţi avut contact cu PHP, ați observat că acolo se folosește tocmai această sintaxă. Deşi soluţia
este rapidă şi elegantă, ea trebuie încă evitată, deoarece multe browser-e nu oferă suport pentru
121
această tehnologie. De exemplu, dacă am activa un astfel de cod în Google Chrome, am observa
următoarea problemă:
Imaginea 13.2
Funcţiile fără nume definit – Anonymous Functions/funcțiile anonime
Funcţiile se pot defini şi cu ajutorul expresiilor pentru crearea funcţiilor (Function Expressions).
Când folosim o astfel de expresie, nu trebuie să mai definim numele funcţiei. Funcţiile care nu au
nume definit se numesc funcţii anonymous/anonime.
Exemplu:
1
2
3
var x = function (a, b){return a + b};
var r = x(2, 3);
document.write(r);<span style="font-size: 14px; text-align:
justify;"> </span>
După cum vedeţi, am folosit expresia pentru crearea funcţiei anonime pe care am atribuit-o
variabilei x. Apoi, această funcţie este accesată prin intermediul variabilei x, aspect prezentat în a
doua linie a codului.
Deseori, aceste funcţii pot fi utile când se folosesc ca parametri ai unei alte funcţii. Să vedem
exemplul următor:
1 setTimeout(function() {alert('hello');}, 5000);<span style="font-size: 14px;
text-align: justify;"> </span>
Funcţia setTimeout() este una dintre funcţiile încorporate care solicită doi parametri. Primul este
codul JavaScript care va fi executat, al doilea este numărul care afișează timpul care va trece
înainte de executarea codului de pe primul parametru. Timpul este exprimat în milisecunde. În
122
cazul nostru, caseta de notificare/alert va apărea după 5 secunde. După cum vedeţi, în locul unui
parametru primitiv, am setat funcţia JavaScript anonymous.
Funcţiile care se apelează singure – Self-Executing Function
Toate funcţiile pe care le-am creat până acum într-un anumit loc trebuiau să fie apelate în mod
explicit pentru a li se executa codul.
Să analizăm exemplul următor:
1
2
3
4
function myFunction(){
alert("Hello!");
}
myFunction();<span style="font-size: 14px; text-align: justify;"> </span>
În acest caz, funcția va fi executată deoarece este apelată în ultima linie a codului – myFunction().
Pe de altă parte, funcţia astfel scrisă nu va fi executată:
1
2
3
4
function myFunction(){
alert("Hello!");
}
Se pune întrebarea cum să marcăm funcţia myFunction, astfel încât să se apeleze de una singură.
Astfel de funcţii se numesc Self-Executing Function, iar sintaxa lor este următoarea:
1
2
3
4
(function myFunction(){
alert("Hello!");
})();<span style="font-size: 14px; text-align: justify;"> </span>
Deci, întreaga funcţie trebuie cuprinsă între paranteze rotunde, după care parantezele trebuie să se
închidă şi să se deschidă încă o dată. Desigur, dacă funcţiei trebuie să i se atribuie un parametru,
ultimele paranteze nu ar fi goale, iar acest parametru s-ar afla între ele.
Să vedem exemplul şi pentru acest caz:
123
1
2
3
(function myFunction(msg){
alert(msg);
})("Hello!");
Funcţiile recursive
Funcţiile care se apelează singure în cadrul corpului lor se numesc funcţii recursive. În unele
cazuri, astfel de funcţii pot fi utile. Un asemenea caz este crearea funcţiei care va calcula factorul
unui număr. De exemplu, factorul numărului 5 este 200, ceea ce se obţine în felul următor:
1 n! = 1*2*3*4*5<span style="font-size: 14px;"> </span>
Să creăm acum funcţia care va calcula valoarea factorială pentru fiecare număr care i se atribuie:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function factorial(num)
{
if (num < 0) {
return -1;
}
else if (num == 0) {
return 1;
}
else {
return (num * factorial(num - 1));
}
}
var result = factorial(5);
document.write(result);<span style="font-size: 14px; text-align:
justify;"> </span>
După cum vedeţi, în blocul else al codului, funcţia se apelează pe sine, dar parametrul se reduce
cu 1.
124
Notă:
Când scrieţi funcţii recursive, ţineţi cont de logica folosită, pentru a nu ajunge în situația în care la
un moment dat funcția să se repete la nesfârșit.
Introducere în DOM
Unitate: 14 din 19 00:13:27
+Rezumat
În această lecţie, vom învăţa principalele concepte ale modelului DOM. DOM – Document Object
Model – este obiectul care reprezintă documentul HTML şi toate componentele sale (formulare,
linkuri, controale etc.). DOM ne oferă posibilitatea să preluăm elemente dintr-un anumit
document. De asemenea, cu ajutorul lui DOM putem să creăm elemente noi în document, să facem
modificări asupra celor existente sau să înlăturăm elementele deja create. DOM este interfaţa de
programare pentru documentele HTML şi XML. Astfel, este posibilă o reprezentare structurată a
documentului, precum şi diferite tehnologii pentru accesarea şi modificarea documentului. Cu
ajutorul lui DOM, putem modifica:
structura documentului;
stilizarea documentului;
conţinutul documentului.
DOM permite reprezentarea documentului sub formă de grupuri de noduri (nodes – noduri) şi de
obiecte cu diferite proprietăţi şi metode. După tot ce am spus până acum, concluzionăm că DOM
reprezintă legătura dintre limbajul de scripting (de programare) şi pagina web în sine.
Să analizăm următoarea imagine:
125
Imaginea 14.1.
Dacă ne uităm cu atenţie, vom vedea că aici este vorba de diferite prezentări ale aceluiaşi document
HTML. În partea stângă, vedem cum este perceput editorul text de acest document. În partea
dreaptă, acelaşi document este prezentat aşa cum îl vede utilizatorul în browser-ul său. A mai
rămas prezentarea din mijloc, pe care o putem considera ca o vedere asupra documentului DOM.
După cum am văzut până acum, tag-urile HTML nu înseamnă foarte mult pentru JavaScript,
deoarece nu este foarte eficient în ceea ce privește manipularea lor. De aceea, JavaScript este foarte
eficient când trebuie manipulate obiectele. Aici intră în scenă DOM care creează o reprezentare
complet orientată pe obiect a documentului manipulat foarte uşor şi rapid de JavaScript.
DOM este standardizat, aşadar W3C (World Wide Web Consortium) asigură standardul susținut de
aproape toate browser-ele moderne. Însă, nu trebuie să uităm că multe browser-e implementează
extensii suplimentare independent de standardul W3C, motiv pentru care trebuie să fim precauţi
când aplicăm funcţiile rare, deoarece există posibilitatea să nu fie susținute de toate browser-ele.
Când utilizăm aceste extensii, este de preferat să consultăm literatura de specialitate pentru a ne
asigura ce suport oferă browser-ele pentru tehnologia pe care vreţi să o aplicaţi. Există o mulţime
de site-uri din care vă puteţi informa în legătură cu diferite metode şi să confirmaţi suportul pentru
ele. Unul dintre cele mai bune site-uri este:
http://www.quirksmode.org/dom/
126
Să vedem prezentarea raportului pentru metoda querySelectorAll():
Imaginea 14.2.
Deci, dacă vrem să folosim această metodă, o găsim pe site-ul menţionat mai sus unde sunt
enumerate browser-ele care o susțin. Concret, observăm că Internet Explorer, până la versiunea 8,
nu susține această metodă, în timp ce versiunea 8 o susține parţial.
Notă:
Dacă vă decideţi să aplicați o metodă cu suport precar printre browser-e, riscaţi ca pagina dvs. să
arate ciudat în unele browser-e sau să-şi piardă în totalitate funcţionalitatea. Totuşi, în cod puteţi
efectua testarea şi puteți să aplicaţi acea metodă sau proprietate pentru care aveți confirmarea că
este susținută de browser.
Înainte de a începe lucrul cu obiectele DOM, vom încerca să realizăm principala structură
HTML/XML.
Fiecare document bazat pe structura XML (HTML) are o anumită ierarhie. Totul începe cu un
element concret care conţine sub-elemente, care la rândul lor conţin alte sub-elemente. O
proprietate foarte importantă în HTML, XML şi în alte ierarhii este că trebuie să existe doar un
element rădăcină. De fapt, XML şi HTML pot fi afișate sub forma unui arbore conceput după
modelul arborelui genealogic. Cel mai vechi strămoş se află în vârf. Sub el se ramifică descendenții
săi, descendenții descendenților săi etc. Elementele care au acelaşi strămoş sunt gemeni. Fiecare
element are propriile sale atribute.
Să vedem asta într-un exemplu:
127
Imaginea 14.3.
Rădăcina se află în vârful tuturor elementelor. Deci, primul nod este documentElement (<html>),
care are doi descendenți. Ambii sunt elemente (<head> şi <body>). Să urmărim acum ramura
stângă a acestui arbore. Elementul head are un descendent care, de asemenea, este de tip element,
şi anume title. Acesta are descendentul al cărui tip nu este element, ci nod textual.
Notă:
Până acum, am menţionat două tipuri de noduri: Element şi Text tip. Pe lângă acestea, mai există
10, deci în total 12 tipuri de noduri în DOM, despre care vom discuta mai târziu.
Să analizăm acum ramura dreaptă a acestui arbore. Elementul body are doi descendenți: h2 şi p,
dar acum situaţia se complică puțin. Observaţi că lângă elementul h2 mai există un dreptunghi
suplimentar. Acesta este atributul. Cu ajutorul lui DOM, putem adăuga, schimba sau înlătura
atributele fiecărui element. Pe lângă atribut, node h2 are şi un descendent, şi anume nodul textual.
Pe de altă parte, avem elementul p, care are trei descendenți. Primul şi al treilea descendent sunt
noduri textuale, în timp ce al doilea descendent este un element nou. La final, elementul are un
descendent care este un nod textual.
Această structură poate avea un număr arbitrar de nivele, dar nivelul zero este întotdeauna
elementul rădăcină.
Am menţionat deja că structura DOM este concepută după modelul arborelui genealogic şi care
sunt elementele arborelui nostru. Acum este momentul propice să analizăm în ce raport de rudenie
128
se află elementele pe care le-am văzut aici. De aceea, haideți să analizăm rudele din unghiul
elementului h2 (elementul încercuit în imagine):
Imaginea 14.4.
Dacă analizăm poziţia elementului h2, observăm că acesta are câteva rude. Prima rudă este
părintele său, respectiv elementul marcat cu 1 în ilustraţie. Dacă de pe poziţia pe care se află
elementul h2 am vrea să-i accesăm părintele, am spune că avem nevoie de parentNode-ul său,
respectiv nodul părinte. Următoarea rudă a elementului nostru h2 este descendentul său sau copilul,
acesta fiind nodul marcat cu 2 în ilustraţie. Dacă de pe poziţia elementului h2 am vrea să efectuăm
acest nod, am solicita nodul firstChild. Mai rămâne să stabilim în ce relaţie se află elementele h2
şi p (element marcat cu 3). După cum vedeţi, aceste două elemente au acelaşi părinte, aşadar în
arborele de familie am spune că sunt fraţi (siblings). Deoarece structura DOM se analizează
întotdeauna de la stânga la dreapta, acesta este elementul p nextSibling pentru elementul h2. Dacă
l-am analiza din unghiul elementului p, am spune că elementul h2 este previousSibling-ul
său. Observaţi că am menţionat diferite expresii precum: parentNode, firstChild, nextSibling etc.
În acest moment nu trebuie să ştiţi unde trebuie scrise în cod, deoarece de aceasta ne vom ocupa
în detaliu în următoarea lecţie, dar este important să înţelegeţi în ce relaţie se pot afla elementele
în arbore.
Acum, când arborele DOM din ilustraţia precedentă ne este clar, să vedem cum arată acest
document în editor:
1
2
<html> <head>
129
3
4
5
6
7
8
9
<title>DOM Tree</title> </head> <body> <h2>Testing</h2> <p>Welcome to <i>JavaScript</i>...</p> </body> </html><span style="font-size: 14px; text-align: justify;"> </span>
Deoarece structura DOM se creează în momentul încărcării paginii, obţinem o prezentare completă
obiectuală a întregului document. Schimbând proprietăţile acestui obiect, de fapt schimbăm
documentul. Dacă ne uităm la HTML-ul pe care tocmai l-am scris pe baza ilustraţiei DOM, vom
vedea că title din acest document este setat la „DOM Tree”. Deci, am putea spune că în prezentarea
obiectuală a documentului, title va fi proprietatea obiectului document. Cum proprietăţile
obiectului se pot accesa cu notaţia dot (vezi lecţia Şirurile asociative şi JavaScript), înseamnă că
proprietatea se poate accesa dacă scriem document.title, care este corect. Modificând această
proprietate, se va modifica şi prezentarea documentului în faţa utilizatorului.
Să vedem exemplul în cod:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html> <head> <title>DOM Tree</title> </head> <body> <h2>Testing</h2> <p>Welcome to <i>JavaScript</i>...</p> <script> document.title = "JavaScript - title"; </script> </body> </html>
Observaţi că, în partea head, title este setat la DOM Tree şi că această proprietate a fost modificată
prin JavaScript, așa că am scris: document.title = "JavaScript - title";
Dacă pornim programul, vom vedea că title se modifică cu ajutorul lui DOM:
130
Imaginea 14.5.
Pe lângă proprietăţi, obiectele au şi diferite metode. Una dintre ele este şi document.write() pe care
am folosit-o deja.
Obiectele conţin şi multe proprietăţi, cu care se defineşte aspectul elementului specific sau al
întregii pagini. De exemplu, să vedem următorul cod cu care schimbăm culoarea de fundal a
paginii prin JavaScript cu ajutorul interfeţei DOM:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html> <head> <title>DOM Tree</title> </head> <body> <h2>Testing</h2> <p>Welcome to <i>JavaScript</i>...</p>
<script> document.bgColor = "yellow"; </script> </body> </html>
După activarea acestui script, veţi vedea că s-a schimbat culoarea de fundal, deşi nu am folosit
stilizarea CSS așa cum ne-am obişnuit până acum, ci am efectuat modificarea schimbând
proprietatea obiectului.
Continuăm cu un exemplu puțin mai complex de modificare a proprietăţilor obiectelor. Să
încercăm să setăm imaginea de fundal în loc să modificăm culoarea de fundal. Este clar că aici e
131
vorba de stilizare cu ajutorul lui DOM; de aceea, am stabilit că trebuie să atribuim
proprietatea style asupra unui element. Deoarece aici este vorba de elementul body (vă este deja
familiar din HTML şi CSS), traiectoria este următoarea:
1 document.body.style<span style="font-size: 14px; text-align:
justify;"> </span>
După aceea trebuie să definim ce proprietate vrem să modificăm. Proprietatea imaginii de fundal
este backgroundImage, de aceea linia noastră de cod arată astfel:
1 document.body.style.backgroundImage
Mai rămâne să adăugăm un link aşa cum am făcut în CSS şi să punem această linie de cod în tag-
urile JavaScript.
Iată şi exemplul:
1
2
3
4
5
6
7
8
9
1
0
1
1
1
2
1
3
1
4
1
5
1
6
<html> <head> <title>DOM Tree</title> </head> <body> <h2>Testing</h2> <p>Welcome to <i>JavaScript</i>...</p> <script>
document.body.style.backgroundImage="url('http://images.all-free-
download.com/images/graphiclarge/beautiful_natural_scenery_04_hd_pictures_16
6229.jpg')";
</script> </body> </html><span style="font-size: 14px; text-align: justify;"> </span>
După activarea acestui cod, fereastra ar trebui să arate ca în imaginea de mai jos:
132
Imaginea 14.6.
Notă:
Dacă nu vă apare imaginea de pe ecran, schimbaţi linkul dintre paranteze.
Manipularea obiectelor HTML
Unitate: 15 din 19 00:27:12
+Rezumat
În această lecţie, vom învăţa cum să manipulăm obiectele HTML. În lecţia precedentă, am discutat
despre DOM şi ne-am familiarizat cu caracteristicile sale prin intermediul obiectelor de la cel mai
înalt nivel.
133
La începutul lecţiei precedente, am menționat că întreaga structură DOM este alcătuită din
noduri (nodes), aşadar avem elementele, atributele şi conţinutul elementelor, dar şi că fiecare dintre
aceste elemente poate fi părintele sau copilul cuiva.
Ştim că documentul HTML începe cu tag-ul HTML, care este rădăcina şi elementul fiecărui
document HTML. Apoi, conține tag-urile head şi body, care sunt copiii (children) elementului
HTML. La final, fiecare sub-element (de exemplu, div) poate să conţină un text în tag-ul body.
Principalul scop al lui HTML DOM este obţinerea unor conţinuturi (texte, valori şi atribute), legate
de anumite elemente ale documentului.
Fiecare document HTML trebuie să aibă un tag iniţial şi final:
1
2
3
<html> ... </html><span style="font-size: 14px;"> </span>
În cadrul acestui element rădăcină, mai avem două elemente importante, şi anume head şi body.
Putem spune că până până aici structura DOM ne este cunoscută, dar în ceea ce privește
ramificarea în continuare a elementelor nu putem decât să facem presupuneri. De aceea, trebuie
să învăţăm să ne deplasăm prin structura documentului şi să obținem elementele de care avem
nevoie.
Deoarece în această lecţie vom pune accentul pe modificarea structurii documentului (nu pe
stilizare), explicaţiile noastre vor fi descrise din acest unghi de vedere. De exemplu, prin DOM
putem crea elemente care nu există în document şi le putem adăuga. Astfel, ramificăm arborele
adăugând noi div, p, h1, h2 şi alte tag-uri. În plus, putem să ştergem elemente existente,
simplificând astfel ramificarea arborelui. Şi, la final, putem să facem modificări asupra elementelor
existente.
Pentru a putea să facem orice din cele menţionate, avem nevoie de nişte mecanisme cu care să
selectăm elementelele din arbore. Ca să adăugăm un element nou, trebuie să ştim cărui element să
îi adăugăm descendentul (pentru că nu vrem să adăugăm noul div oriunde pe pagină, ci exact acolo
unde avem nevoie de el). Pentru a şterge un element, în primul rând trebuie să-l găsim, pentru ca
JavaScript să ştie ce trebuie să înlăture din arbore şi, desigur, când vrem să schimbăm un element,
trebuie să-l selectăm pentru a-l modifica.
Cum găsim un element în arbore? Există mai multe modalităţi în care putem găsi un anumit
element, dar iată-le pe cele mai frecvente trei:
getElementById(),
getElementsByClassName(),
getElementsByName(),
getElementsByTagName().
134
Căutarea elementelor după id – getElementById()
Pentru a găsi un element în document, trebuie să avem cel puţin o informaţie despre el. În căutare
ne pot fi de folos diferite caracteristici ale elementului (id-ul elementului, clasa căreia îi aparţine,
numele tag-ului pe care îl are, poziţia între elemente în cadrul nodului părinte etc.). Cel mai uşor
găsim un element după id, deoarece numai în acest fel suntem siguri că în document există doar
un element cu un astfel de id, aşadar suntem siguri că am găsit exact elementul de care avem
nevoie.
Metoda getElementById() se apelează asupra obiectului document şi, de fapt, îi spune browser-
ului că avem nevoie de elementul care se află în document, care are id-ul pe care l-am menţionat
ca parametru al acestei metode.
Să vedem un exemplu în acest sens:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html> <head> <title>DOM</title> </head> <body> <div id="div_1"> <p id="p_1">Text 1</p> <p id="p_2">Text 2</p> <p>Text 3</p> </div>
<script> var paragraph_1 = document.getElementById('p_2'); </script> </body> </html><span style="font-size: 15.399998664856px; text-align:
justify;"> </span>
Observaţi atributele id care apar în acest exemplu:
div_1 – se referă la tag-ul div;
p_1 – se referă la tag-ul p;
p_2 – se referă la al doilea tag p.
Al treilea paragraf nu are propriul id şi cu ajutorul metodei getElementById() nu am putea selecta
acest tag. În tag-urile script, definim variabila paragraph_1. În continuare, această variabilă va
prezenta în cod tag-ul p cu id-ul p_2. Asupra obiectului document, apelăm metoda
getElementById() şi, între paranteze, ca atribut, distribuim numele ID-ului elementului pe care îl
căutăm.
135
Am reuşit să adăugăm elementul şi să asigurăm variabila care îl va prezenta, dar în continuare nu
am făcut nimic cu acest element, motiv pentru care aspectul pe pagină arată în felul următor:
Text 1
Text 2
Text 3
Să presupunem că vrem să modificăm conţinutul elementului selectat. Vom face aceasta
modificând proprietatea innerHTML, cu care stabilim conţinutul elementului perceput ca şi cod
HTML.
Exemplu:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html> <head> <title>DOM</title> </head> <body> <div id="div_1"> <p id="p_1">Text 1</p> <p id="p_2">Text 2</p> <p>Text 3</p> </div> <script> var paragraph_1 = document.getElementById('p_2'); paragraph_1.innerHTML = "This is a change!"; </script>
</body> </html><span style="font-size: 14px;"> </span>
Acum, ieşirea pe ecran va fi diferită:
Text 1
This is a change!
Text 3
Important: Trebuie să ţinem cont că elementul este încărcat înainte de a încerca să-l găsim în
document. De exemplu, un cod scris astfel nu va funcţiona:
1
2
3
4
<html> <head> <title>DOM</title> </head> <body>
136
5
6
7
8
9
10
11
12
13
14
15
16
<script> var paragraph_1 = document.getElementById('p_2'); paragraph_1.innerHTML = "This is a change!"; </script> <div id="div_1"> <p id="p_1">Text 1</p> <p id="p_2">Text 2</p> <p>Text 3</p> </div> </body> </html><span style="font-size: 14px;"> </span>
Să analizăm şi o altfel de situaţie în exemplul următor:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html> <head> <title>DOM</title> </head> <body> <p id="p_1">Text 1</p> <br><script> var paragraph_1 = document.getElementById('p_1'); paragraph_1.innerHTML = "This is a change 1!"; var paragraph_2 = document.getElementById('p_2'); paragraph_2.innerHTML = "This is a change 2!"; </script> <br><p id="p_2">Text 2</p> </body> </html><span style="font-size: 14px;"> </span>
În tag-urile script, am încercat să efectuăm modificarea asupra ambelor tag-uri p aflate în
document, dar modificarea a avut succes numai în cazul tag-ului p cu id-ul „p_1”, deoarece acest
tag a fost încărcat înainte de a începe căutarea. Al doilea tag nu s-a modificat, deoarece am încercat
să-l găsim înainte de a apărea în structura noastră DOM, de aceea modificarea nu a avut succes.
Dacă verificăm în consolă, vom vedea eroarea care ne avertizează că nu se poate seta o proprietate
pe ceva ce nu există (null):
137
Imaginea 15.1.
Notă:
După cum ştim deja din experiența de până acum cu HTML şi CSS, identificatorul id trebuie să
fie unic pentru pagină. Deci, un element trebuie să aibă un singur id, nu mai multe. Totuşi, dacă
creaţi mai multe elemente cu acelaşi id, browser-ul nu își va înceta activitatea şi nu va fi raportată
nicio eroare, dar metoda getElementById() va returna doar primul element cu id-ul marcat, în timp
ce celelalte elemente vor fi neglijate.
Căutarea elementelor după numele clasei – getElementsByClassName()
Nu trebuie să definim id-ul fiecărui element pentru a reuşi să-l livrăm, deoarece putem ajunge şi
altfel la element. Un alt mod este folosind clasa căreia îi aparţine elementul.
De aceea, haideți să vedem următorul exemplu:
138
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html> <head> <title>DOM</title> </head> <body> <p>Text 1</p> <p class="myClass_1">Text 2</p> <p class="myClass_1">Text 3</p> <p>Text 4</p> <p>Text 5</p> <p class="myClass_2">Text 6</p> <script> var paragraphs = document.getElementsByClassName('myClass_1'); </script> </body> </html><span style="font-size: 14px; text-align: justify;"> </span>
După cum vedeţi, în codul care formează acest exemplu avem 6 tag-uri p, iar unele au clase
definite. Două tag-uri p au aceeaşi clasă, în timp ce ultimul tag p are numele clasei care se
deosebeşte de altele. Să presupunem că vrem să selectăm tag-ul p, care are conţinutul „Text 3”.
Vedem că acest tag p are numele clasei „myClass_1”. De aceea, în tag-urile script definim
variabila paragraphs şi îi atribuim rezultatul pe care îl obţinem de la
document.getElementsByClassName('myClass_1'). Însă, aici avem o problemă, deoarece avem
nevoie doar de tag-ul p, care are conţinutul „Text 3”, iar ambele tag-uri au aceeaşi clasă. De aceea,
această metodă va aduna, totuşi, ambele elemente p şi le va pune în variabila paragraphs. Acum,
variabila paragraphs devine colecţia de elemente sau lista de noduri (nodeList). Această listă se
poate accesa ca un şir indexat. Astfel, pe poziţia 0 va fi setat primul tag p, iar pe poziţia 1, al doilea
tag p.
Notă:
Nu uitaţi că toate metodele care adună colecţia de noduri au litera s în nume:
getElementsByClassName(), getElementsByTagName().
Să folosim acum informaţia şi să facem modificări în paragraful cu textul „Text 3”:
1
2
3
4
5
6
7
8
<html> <head> <title>DOM</title> </head> <body> <p>Text 1</p> <p class="myClass_1">Text 2</p> <p class="myClass_1">Text 3</p> <p>Text 4</p> <p>Text 5</p>
139
9
10
11
12
13
14
15
16
17
18
19
<p class="myClass_2">Text 6</p> <script> var paragraphs = document.getElementsByClassName('myClass_1'); paragraphs[1].innerHTML = "This is a change 1!"; </script> </body> </html><span style="font-size: 14px; text-align: justify;"> </span>
Notă:
Metoda getElementsByClassName() returnează node list chiar şi atunci când în document se
găsește doar un element cu numele marcat al clasei. Să vedem aceasta în următoarele exemple.
Exemplul va funcţiona astfel:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html> <head> <title>DOM</title> </head> <body> <p>Text 1</p> <p class="myClass_1">Text 2</p> <p class="myClass_1">Text 3</p> <p>Text 4</p> <p>Text 5</p> <p class="myClass_2">Text 6</p> <script> var paragraphs = document.getElementsByClassName('myClass_2'); paragraphs[0].innerHTML = "This is a change 1!"; </script>
</body> </html><span style="font-size: 14px; text-align: justify;"> </span>
În timp ce următorul exemplu nu va funcţiona corect, indiferent că există doar un tag p al clasei
myClass_2:
1
2
3
<html> <head> <title>DOM</title> </head>
140
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<body> <p>Text 1</p> <p class="myClass_1">Text 2</p> <p class="myClass_1">Text 3</p> <p>Text 4</p> <p>Text 5</p> <p class="myClass_2">Text 6</p>
<script> var paragraphs = document.getElementsByClassName('myClass_2'); paragraphs.innerHTML = "This is a change 1!"; </script>
</body> </html><br><br>
Selectarea elementelor pe baza atributului name – getElementsByName()
Această metodă returnează un şir de elemente care au acelaşi atribut name, a cărui valoare se
suprapune cu parametrul metodelor. Trebuie să observăm că nu toate elementele au atributul name,
ci doar unele.
De exemplu, elementele formularului HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html> <head> <title>DOM</title> </head> <body> <form> <input type="text" name="name" /> <input type="password" name="password" /> </form> <script> var name = document.getElementsByName("name"); var pass = document.getElementsByName("password"); name[0].value = "James"; pass[0].value = "Smith100"; </script> </body> </html><span style="font-size: 14px; text-align: justify;"> </span>
141
Deoarece mai multe elemente pot avea aceeaşi valoare pentru atributul name, şi metoda
getElementsByName() returnează lista node, nu trebuie să uităm să menţionăm indexul între
paranteze pătrate. În acest exemplu, ne-am folosit de ambele proprietăţi menționate mai devreme,
mai ales de proprietatea value. Astfel, manipulăm conţinutul formularului input. Reţineţi această
proprietate, deoarece o vom folosi des pentru diferite scopuri, în special când apar cereri de
validare a introducerilor de utilizator.
Suplimentul pentru selectarea elementelor pe baza numelui din lista formularului
Node list-ul formularului care se află pe o pagină se poate furniza în felul următor:
1 document.forms<span style="font-size: 14px;"> </span>
Această listă de noduri (node list), ca oricare alta, se accesează ca un şir indexat, aşadar primul
formular pe pagină se poate furniza dacă scriem:
1 document.forms[0]<span style="font-size: 14px; text-align:
justify;"> </span>
deoarece 0 este primul index în şir. După furnizarea formularului, elementele sale pot fi accesate
pe baza atributului name, cu ajutorul adnotării dot.
Să vedem exemplul de mai devreme, dar realizat astfel:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html> <head> <title>DOM</title> </head> <body> <form> <input type="text" name="name" /> <input type="password" name="password" /> </form> <script> document.forms[0].name.value = "James"; document.forms[0].password.value = "Smith100"; </script>
</body> </html>
Selectarea elementelor pe baza numelui tag-ului – getElementsByTagName()
142
Această metodă oferă un rezultat identic cu cel precedent (şirul de obiecte), dar ca şi condiţii de
căutare preia un anumit nume (tip) al tag-ului precum div, p, img etc. De aceea, următorul exemplu
va fi valid şi pe lângă faptul că tag-urile div nu au niciun fel de identificare unică.
Trebuie să ţinem cont că prin această metodă, dacă este aplicată asupra obiectului, vor fi selectate
toate tag-urile cu numele marcat, oriunde s-ar afla.
Să vedem exemplul:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html> <head> <title>DOM</title> </head> <body> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul>
<script> var items = document.getElementsByTagName('li'); items[1].innerHTML = "This is a change!"; </script> </body> </html><span style="font-size: 14px; text-align: justify;"> </span>
În acest document, avem trei tag-uri li şi niciunul dintre ele nu are definit atributul id, class sau
name. Dacă am vrea să furnizăm al doilea element în şir, în primul rând am selecta toate tag-urile
li, apoi am accesa elementul care are indexul 1, respectiv care se află pe a doua poziţie. De aceea,
rezultatul pe pagină este următorul:
Item 1
This is a change!
Item 3
Utilizarea selectorului CSS în DOM
Utilizatorii care se întâlnesc prima dată cu manipularea DOM deseori sunt fascinaţi de această
metodă, deoarece pot folosi tot ce ştiu legat de selectorii CSS pe care îi au, furnizând astfel
documente foarte repede şi simplu. Pur și simplu, cu ajutorul a două metode şi a selectorului CSS,
puteţi furniza fiecare element din document.
Selectarea unui element – querySelector()
143
Folosind metoda querySelector(), va fi returnat doar un element. Între paranteze, string-ul care
arată ca selectorul CSS trebuie trimis ca parametru.
Să vedem exemplul:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html> <head> <title>DOM</title> </head> <body> <ul> <li>Item 1</li> <li id="myId_1">Item 2</li> <li>Item 3</li> </ul> <script> var item = document.querySelector('#myId_1'); item.innerHTML = "This is a change!"; </script>
</body> </html>
Selectarea mai multor elemente – querySelectorAll()
Metoda querySelectorAll() funcţionează la fel ca metoda precedentă, cu diferenţa că în acest caz
vor fi selectate toate elementele care îndeplinesc condiţia menţionată între paranteze.
Să vedem un exemplu în acest sens:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html> <head> <title>DOM</title> </head> <body> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul>
<script> var items = document.querySelectorAll('li'); items[2].innerHTML = "This is a change!"; </script> </body>
144
15
16
17
18
</html>
Selectarea descendenților
În diferite situaţii, poate fi foarte util să furnizăm elementul care este primul descendent al unui
element sau ultimul descendent, dacă nu suntem siguri câţi descendenți are elementul.
Să vedem, mai întâi, reprezentarea grafică a acestui caz:
Imaginea 15.2.
În exemplu, ca nod părinte a fost setat body, dar poate fi orice element. Principiul este întotdeauna
acelaşi. Deci, dacă de pe poziţia de părinte (body) am vrea să accesăm primul descendent (div-ul
din stânga), am scrie această linie de cod:
1 document.body.firstChild
Aceeaşi logică se folosește şi pentru accesarea ultimului descendent, doar că acum este vorba de
proprietatea lastChild.
Observăm că în acest fel nu putem furniza tag-ul ul oricărui alt descendent care nu se află pe prima
sau pe ultima poziţie. De aceea, există proprietatea childNodes, care returnează colecţia tuturor
nodurilor care sunt descendenți ai nodului asupra căruia este apelată proprietatea.
Să vedem reprezentarea grafică:
145
Imaginea 15.3.
Astfel, elementul ul a fost accesat în felul următor:
1 document.body.childNodes[1]
Problemele nodurilor nedorite – Whitespace nodes
Dacă aţi încercat să aplicaţi firstChild, lastChild şi childNodes din exemplul precedent, codul dvs.
nu se comportă aşa cum aţi fi vrut. Aceasta este o consecinţă a problemelor cauzate de spaţiul alb
dintre elementele din document.
Să vedem reprezentarea grafică care ne va ajuta să înţelegem despre ce este vorba:
146
Imaginea 15.4.
Dacă am scrie elementele HTML pe un singur rând fără spaţii nu ar fi nicio problemă, dar când
dăm clic pe Enter pentru a trece pe un rând nou şi pentru a creşte transparenţa documentului, deşi
noi nu vedem acest lucru în editor, se creează un nou semn pe care DOM îl percepe ca nod. De
aici, pătrăţelele goale din ilustraţia de mai sus, pe care le putem numi rude nedorite în arborele
nostru genealogic. Să ne amintim acum de metoda firstChild despre care am discutat. Dacă o
apelăm asupra elementului body, aceasta, ca primul child, va returna nodul alb, dar de fapt, am
vrut să furnizăm div.
Există mai multe modalităţi de a depăşi această metodă:
evitarea creării acestor noduri (nu se lasă spaţiu între elemente);
crearea funcţiei care va testa dacă este vorba de nodul dorit sau nedorit;
folosirea proprietăţilor specializate pentru selectarea nodurilor.
Primul mod
Scrierea unui cod HTML pe o linie fără spaţiu ar fi o problemă, iar documentul ar fi opac în
totalitate. Pentru a păstra cât de cât o transparenţă, se poate folosi cuvântul cu care anulăm
închiderea tag-ului precedent. Aceasta va crea goluri în tag-urile care nu ne vor face probleme, dar
vom păstra şi un anumit nivel de transparenţă.
Exemplu:
1 <html>
147
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<head> <title>DOM</title> </head> <body ><ul ><li>Item 1</li ><li>Item 2</li ><li>Item 3</li ></ul>
<script> var item = document.body.firstChild.lastChild; item.innerHTML = "This is a change!"; </script> </body> </html><span style="font-size: 14px;"> </span>
Notă:
Acesta este principalul mod de rezolvare a problemelor spaţiilor goale în document şi nu trebuie
folosit.
Al doilea mod
Fiecare nod are propriul său tip. Există 12 tipuri pentru nodurile care sunt prezentate în următorul
tabel:
NodeType Named Constant
1 ELEMENT_NODE
2 ATTRIBUTE_NODE
3 TEXT_NODE
4 CDATA_SECTION_NODE
5 ENTITY_REFERENCE_NODE
6 ENTITY_NODE
7 PROCESSING_INSTRUCTION_NODE
8 COMMENT_NODE
9 DOCUMENT_NODE
10 DOCUMENT_TYPE_NODE
11 DOCUMENT_FRAGMENT_NODE
12 NOTATION_NODE
Tabelul 15.1.
148
Pentru a depăşi problemele legate de nodurile goale, putem crea funcţii specifice, care vor furniza
numai acele noduri al căror tip îndeplineşte nevoile specifice ale programatorului din acel moment.
Crearea acestor funcţii necesită utilizarea unor funcţionalităţi ale lui JavaScript care depăşesc acest
curs, aşadar nu ne vom ocupa în detaliu de ele.
Al treilea mod
Al treilea mod este şi ultimul și în același timp cel mai des folosit pentru a rezolva problema
nodurilor goale. Deci, folosim proprietăţi specializate care vor returna nodurile care sunt elemente,
iar dat fiind că nodurile goale reprezintă noduri text, acestea vor fi sărite, aşadar şi problema
noastră este rezolvată. Deci, aplicarea este la fel, doar numele proprietăţii este diferit.
Să vedem tabelul:
Testează toate nodurile. Testează numai nodurile Element.
firstChild firstElementChild
lastChild lastElementChild
childNodes children
nextSibling nextElementSibling
previousSibling previousElementSibling
Tabelul 15.2.
În tabel, observaţi două proprietăţi noi, nextSibling şi previousSibling (precum şi perechile lor:
nextElementSibling şi previousElementSibling).
Să privim ilustraţia pentru a înţelege mai bine aceste proprietăţi:
149
Imaginea 15.5.
Așadar, logica este foarte simplă. Dacă se află pe poziţia elementului ul, în partea stângă se află
previousSibling (previousElementSibling), adică elementul div stâng. În partea dreaptă, este
nextSibling (nextElementSibling), adică elementul div drept.
Furnizarea nodului părinte
Până acum am învăţat cum să ne deplasăm în arbore de pe poziţiile de sus către cele de jos
(firstChild, lastChild, childNodes, firstElementChild, lastElementChild, children). De asemenea,
am învăţat şi cum să ne deplasăm între elemente de la acelaşi nivel sau pe orizontală (nextSibling,
previousSibling, nextElementSibling, previousElementSibling). Mai rămâne să învăţăm cum să ne
deplasăm pe verticală de jos în sus, și anume către nodul părinte. Deoarece părintele este
întotdeauna unul, la fel şi proprietatea: parentNode.
Să vedem reprezentarea grafică:
Imaginea 15.6.
Să vedem exemplul pe un cod:
1
2
3
4
5
6
7
8
9
10
<html> <head> <title>DOM</title> </head> <body> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> <script>
150
11
12
13
14
15
16
17
18
var li = document.querySelector('li'); li.parentNode.innerHTML += "<li>New li tag!</li>"; </script> </body> </html><span style="font-size: 14px;"> </span>
După cum puteţi observa, cu ajutorul lui querySelector am furnizat primul element li. Apoi, cu
ajutorul proprietăţii parentNode am ajuns la elementul ul, căruia la final i-am adăugat noul tag li.
Notă:
Folosim operatorul += deoarece vrem ca şi tag-urile existente în elementul ul să fie păstrate.
Stilizarea şi manipularea atributelor
Unitate: 16 din 19 00:15:11
+Rezumat
În lecţia precedentă am învăţat că cel mai important lucru în ceea ce privește utilizarea elementele
DOM, este să selectăm elementele în document. Acum, ne vom îmbogăți cunoştinţele şi vom
învăţa cum să manipulăm atributele elementelor pe care le-am adăugat.
Manipularea atributelor ne oferă mari posibilităţi de stilizare, aşadar în această lecţie vom învăţa
cum să manipulăm stilurile CSS (Cascade Style Sheets).
După cum ştim deja, elementele HTML pot avea atribute diferite. Unele se referă la stilizare, altele
la denumirea elementului şi identificare, în timp ce al treilea tip se referă la înregistrarea unui
eveniment legat de elementul dat. Toate aceste elemente se setează uşor în codul HTML, după ce
am menţionat numelui atributului şi i-am atribuit o valoare când am creat elementul. Însă,
atributele identificate astfel asigură o dinamică foarte mică sau aproape inexistentă pe pagină. Dacă
trebuiau să fie prevăzute şi scrise în timpul scrierii codului HTML în sine, ulterior nu mai puteau
fi schimbate. Într-adevăr, HTML5 şi CSS3, cu ajutorul unor funcţionalităţi îmbunătăţite, pot atinge
un anumit obiect de interactivitate, dar puterea lor în comparație cu JavaScript este neglijabilă.
Atunci, putem controla atributele prin JavaScript? Răspunsul este da și în acest scop avem o
mulţime de metode şi proprietăţi care pot fi aplicate asupra obiectelor.
Să ne amintim că elementele HTML din structura DOM devin nodes. Nodurile sunt obiecte şi, ca
şi celelalte elemente, pot avea proprietăţi şi metode. Folosindu-ne de această logică, după care
elementele HTML devin obiecte, putem presupune că atributele vor deveni proprietăţile acestui
obiect. Pe lângă asta, dacă obiectului node îi adăugăm un atribut care nu reprezintă atributul său,
151
această proprietate nu va avea efect pe pagina HTML, dar va exista regulamentar pentru obiectul
căruia i-a fost atribuit.
Să vedem un exemplul edificator:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html> <head> <title>DOM</title> </head> <body>
<p id="p_1">Paragraph 1</p> <script> var p1 = document.getElementById("p_1"); p1.id = "new_id"; </script>
</body> </html><span style="font-size: 14px; text-align: justify;"> </span>
În document, a fost creat tag-ul p cu atributul id, care are valoarea p_1. Apoi, se execută JavaScript
scris în tag-urile unde mai întâi selectăm elementul p şi îl punem în variabila p1. Folosindu-ne de
logica pe care am menţionat-o în paragraful precedent, atributul id este perceput ca o proprietate a
noului obiect p1, de aceea îl şi accesăm ca pe orice altă proprietate a obiectului, respectiv cu
ajutorul adnotaţiei not:
1 p1.id<span style="font-size: 14px; text-align: justify;"> </span>
Atribuind o nouă valoare acestei proprietăţi, vom efectua modificarea şi în documentul HTML,
deoarece proprietatea id există ca atribut pentru tag-ul p în document. După linia:
1 p1.id = "new_id";<span style="font-size: 14px; text-align:
justify;"> </span>
valoarea veche a id-ului (p_1) va fi transcrisă ca una nouă (new_id).
Să ne convingem de aceasta analizând documentul prin opţiunea Inspect element din browser:
152
Imaginea 16.1.
În acest fel, putem manipula toate atributele elementului. Acest lucru pare foarte simplu deoarece
trebuie doar să adăugăm elementul, să punem punct şi să dăm un nume atributului, după care putem
face cu el ce vrem. Însă, poate apărea o problemă atunci când se ajunge la un conflict între numele
atributelor şi numele cuvântului-cheie pe care JavaScript l-a rezervat deja.
Să vedem exemplul:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html> <head> <title>DOM</title> </head> <body>
<p id="p_1" class="myClass_1">Paragraph 1</p> <script> var p1 = document.getElementById("p_1"); //space for code </script>
</body> </html><span style="font-size: 14px; text-align: justify;"> </span>
Codul este similar cu cel precedent, dar acum tag-ul nostru p posedă şi atributul class, care are
valoarea myClass_1. Dacă am vrea ca acestui atribut să-i modificăm valoarea la new_class,
folosindu-ne de logica pe care am folosit-o până acum, în loc de comentariu (//space for code) am
scrie:
153
1 p1.class = "new_class";<span style="font-size: 14px; text-align: justify;"> </span>
Totuşi, codul nu va funcţiona. De ce? Motivul este conflictul dintre numele proprietăţii atributelor
şi cuvintele rezervate în JavaScript - > class. De fapt, acest cuvânt se foloseşte în codul JavaScript,
dar întâmplător este şi numele atributului pentru elementul HTML. Pentru a evita acest conflict,
schimbăm numele proprietății, aşadar accesăm atributul prin proprietatea className.
Să vedem exemplul:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html> <head> <title>DOM</title> </head> <body> <p id="p_1" class="myClass_1">Paragraph 1</p>
<script> var p1 = document.getElementById("p_1"); p1.className = "new_class"; </script> </body> </html><span style="font-size: 14px; text-align: justify;"> </span>
De data aceasta, codul va funcţiona fără probleme, deoarece nu există niciun conflict între numele
proprietăţii obiectului şi al cuvântului rezervat. Ne vom convinge de acest lucru verificând dacă
numele clasei a fost într-adevăr modificat:
Imaginea 16.2.
Notă:
154
Pe baza aceluiaşi principiu, se ajunge la un conflict între atributul for şi cuvântul-cheie cu acelaşi
nume, pe care îl folosim pentru a crea bucla. De aceea, în loc de proprietatea for scriem htmlFor.
Un mod mai simplu de manipulare a obiectelor
Acest mod de adăugare şi manipulare a atributelor, despre care am vorbit până acum, se foloseşte
foarte des deoarece accelerează scrierea codului şi, deseori, este foarte practic (în special când
stilizăm elementul). În acelaşi timp însă trebuie să ţinem cont de numele atributului şi cuvintele
rezervate şi să reţinem denumirile ciudate ale atributelor precum: className pentru atributul class
sau htmlFor pentru atributul for. Există vreo posibilitate să nu reţinem aceste nume ciudate şi totuși
să nu ne facem griji, să numim fiecare atribut cu propriul nume în tag-urile JavaScript? Răspunsul
este DA, iar rezolvarea o prezintă următoarele metode:
getAttribute();
setAttribute();
removeAttribute();
hasAttribute().
Adăugarea valorii atributului – getAttribute()
Metoda getAttribute() se foloseşte doar pentru a adăuga valoarea unui atribut. Ca parametru,
solicită numele atributului pe care îl căutăm.
Notă:
În cazul acestei metode, ca şi al celorlalte trei, fiecare atribut are numele său adevărat. Deci,
atributul class este class, nu className, iar atributul for este for, nu htmlFor.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html> <head> <title>DOM</title> </head> <body> <p id="p_1"></p> <script> var p1 = document.getElementById("p_1"); var x = p1.getAttribute('id'); document.write(x); </script> </body> </html><span style="font-size: 14px; text-align: justify;"> </span>
155
15
Variabila x devine string, care este returnat ca rezultat atunci când asupra obiectului p1 se apelează
metoda getElementById(), căreia îi este atribuit ca parametru string-ul care reprezintă numele
atributului căutat.
Setarea valorii atributului – setAttribute()
Deoarece fiecare atribut are propriul nume şi propria valoare, ne aşteaptăm ca această metodă să
solicite două argumente. Primul argument este numele atributului, în timp ce al doilea este valoarea
atributului marcat.
Notă:
Nu contează dacă atributul a fost deja setat pentru element sau nu. Dacă atributul există, valoarea
sa va fi modificată, iar dacă atributul nu există, va fi creat.
Exemplu de setare a atributului class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html> <head> <title>DOM</title> </head> <body> <p id="p_1"></p> <script> var p1 = document.getElementById("p_1"); p1.setAttribute('class', 'new_class');
document.write(p1.getAttribute('class')); </script> </body> </html>
Ștergerea atributului – removeAttribute()
Metoda removeAttribute() solicită, în mod logic, doar un parametru, string-ul care reprezintă
numele atributului ce trebuie înlăturat. Desigur, metoda trebuie să fie apelată asupra nodului al
cărui atribut trebuie şters.
156
Exemplu:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html> <head> <title>DOM</title> </head> <body> <p id="p_1" style="color: red">Text 1</p>
<script> var p1 = document.getElementById("p_1"); p1.removeAttribute('style'); </script> </body> </html>
Stilizarea cu ajutorul atributului style
Dacă v-aţi întâlnit deja cu CSS, acest atribut nu vă este străin. Principalul scop al atributului style
este să definească niște proprietăţi legate de aspectul elementului HTML. Adesea, vom dori să
executăm dinamic o modificare legată de aspectul paginii. Aceasta se poate realiza prin aplicarea
lui JavaScript, care ne permite să modificăm valoarea care se află în cadrul atributului style.
De aceea, să ne amintim de CSS şi proprietatea de modificarea dimensiunii fontului: font-size.
După cum vedem, această proprietate este de fapt un fel de combinație între cuvintele font şi size,
între care se pune o liniuţă (-). Desigur, aceasta nu este singura proprietate din CSS creată din două
cuvinte separate prin semnul -. Însă, proprietatea nodes nu posedă acest semn, ci foloseşte
următoarea logică: dacă trebuie definit numele proprietăţii care va marca font-size, pentru a evita
liniuţa (-), ștergem acest semn şi unim cuvintele. Apoi, pentru claritate, prima literă a celui de-al
doilea cuvânt se schimbă în majusculă, iar la final avem acest rezultat:
fontSize
Regula se foloseşte pentru multe proprietăţi, dar nu pentru toate. Totuşi, dacă cunoaşteţi CSS,
puteți presupune cu uşurinţă cum arată proprietatea corespunzătoare.
Iată tabelul:
CSS JavaScript
background Background
background-attachment backgroundAttachment
background-color backgroundColor
157
background-image backgroundImage
background-position backgroundPosition
background-repeat backgroundRepeat
border Border
border-bottom borderBottom
border-bottom-color borderBottomColor
border-bottom-style borderBottomStyle
border-bottom-width borderBottomWidth
border-color borderColor
border-left borderLeft
border-left-color borderLeftColor
border-left-style borderLeftStyle
border-left-width borderLeftWidth
border-right borderRight
border-right-color borderRightColor
border-right-style borderRightStyle
border-right-width borderRightWidth
border-style borderStyle
border-top borderTop
border-top-color borderTopColor
border-top-style borderTopStyle
border-top-width borderTopWidth
border-width borderWidth
clear Clear
clip Clip
color Color
cursor Cursor
display Display
filter Filter
font Font
font-family fontFamily
font-size fontSize
font-variant fontVariant
font-weight fontWeight
height Height
left Left
letter-spacing letterSpacing
line-height lineHeight
158
list-style listStyle
list-style-image listStyleImage
list-style-position listStylePosition
list-style-type listStyleType
margin Margin
margin-bottom marginBottom
margin-left marginLeft
margin-right marginRight
margin-top marginTop
overflow Overflow
padding Padding
padding-bottom paddingBottom
padding-left paddingLeft
padding-right paddingRight
padding-top paddingTop
page-break-after pageBreakAfter
page-break-before pageBreakBefore
position Position
float styleFloat
text-align textAlign
text-decoration textDecoration
text-decoration: blink textDecorationBlink
text-decoration: line-through textDecorationLineThrough
text-decoration: none textDecorationNone
text-decoration: overline textDecorationOverline
text-decoration: underline textDecorationUnderline
text-indent textIndent
text-transform textTransform
top Top
vertical-align verticalAlign
visibility Visibility
width Width
z-index zIndex
Tabelul 16.1.
Să vedem un exemplu de aplicare a unei proprietăţi:
159
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html> <head> <title>DOM</title> </head> <body> <p id="p_1">Text 1</p> <script> var p1 = document.getElementById("p_1"); p1.style.fontSize = "36px"; </script>
</body> </html><span style="font-size: 14px; text-align: justify;"> </span>
Deoarece logica aplicării tuturor celorlalte proprietăţi este identică, în continuare nu ne vom mai
ocupa de această temă.
Evenimentele şi procesarea lor
Unitate: 17 din 19 00:18:01
+Rezumat
În această lecţie, vom învăţa cum putem lucra în JavaScript cu evenimentele. Momentul în care
începem să monitorizăm evenimentele pe pagină poate fi considerat momentul în care începe
adevărata interacţiune a utilizatorului cu pagina. Ascultând activităţile utilizatorului, JavaScript
poate determina comportamentul paginii. Există diferite evenimente pe care le putem asculta pe
pagină (clicul cu mouse-ul, apăsarea pe o tastă de pe tastatură, intrarea cursorului în câmpul unui
element etc.). Mai întâi, trebuie să menţionăm că nu toate evenimentele depind de utilizator, ele
depind şi de alţi factori care influenţează pagina.
Din momentul în care emite pagina web, browser-ul ține evidenţa tuturor obiectelor care se află
pe o anumită pagină. Fiecare obiect posedă anumite atribute care sunt ascultate. De exemplu, ce
putem face cu o tastă? O putem apăsa sau elibera, putem trece cu mouse-ul peste ea sau o putem
glisa peste un text sau obiect. Pe de altă parte, caseta de text (text box) mai poate susține şi
introducerea textului. Acestea sunt toate evenimentele pe care le poate recunoaşte browser-ul,
deoarece sunt implicite în declaraţia acestor obiecte, iar apariţia lor este, de fapt, momentul în care
începem acţiunea. Desigur, cu condiţia ca înainte de aceasta, undeva în programul nostru, să fi
adus la cunoştinţă browser-ului că vrem să ni se raporteze un anumit eveniment, respectiv să ni se
aducă la cunoştinţă că a avut loc.
Deşi sună complicat, după tot ce am învăţat până acum, această parte va fi destul de simplu de
înţeles şi implementat, deoarece este vorba de locul dintre o funcţionalitate şi obiectele de pe
pagină.
160
Să observăm, în primul rând, prezentarea grafică a exemplului pentru care ulterior vom scrie
codul:
Imaginea 17.1.
În această ilustraţie avem cel mai simplu exemplu (dar, complet funcţional) de setare a lui
eventlistener. După cum probabil v-ați dat seama şi singuri, în acest caz evenimentul este prezentat
cu atributul care are un conţinut. Tocmai acest conţinut reprezintă reacţia la eveniment, iar reacţia
este un cod JavaScript. Elementele asupra cărora se definesc evenimentele pot fi diferite (nu doar
tastele, ci şi elementele de tip: div, p, img etc.). Și evenimentele pot fi diferite, dar în ilustraţia
noastră este prezentat cel mai folosit atribut onclick. La final, între ghilimele se scrie codul
JavaScript, care va fi executat în momentul în care este înregistrat evenimentul.
Să vedem acum acelaşi exemplu aplicat pe un cod:
1 <button type="button" onclick="alert('Button is clicked!')">Click here</button>
După cum vedeţi, este suficientă o singură linie de cod pentru ca exemplul nostru să funcționeze.
Notă:
Când codul JavaScript se scrie între ghilimele ca şi conţinut al atributului, nu se pun tag-urile
<script></script>.
Nu există nicio limită pentru numărul de atribute event care se pot defini asupra elementului.
Evenimentele şi funcţiile
Exemplul precedent este corect dacă vrem ca script-ul nostru să scrie o casetă cu mesaj, dar dacă
dorim o logică mai serioasă pe care să o activeze un anumit eveniment, acest acces nu este suficient
și trebuie să scriem multe linii de cod separate prin punct şi virgulă doar într-un singur atribut.
Următoarea linie reprezintă o practică nerecomandabilă:
161
1 <button type="button" onclick="alert('Button is clicked!'); document.write('New content...')">Click here</button><span style="font-size:
14px; text-align: justify;"> </span>
În loc, logica trebuie plasată într-o funcţie specială, care trebuie apelată la iniţializarea
evenimentului. Următorul exemplu este corect:
1
2
3
4
5
6
7
<button type="button" onclick="myFunction()">Click here</button> <script> function myFunction(){ alert('Button is clicked!'); document.write('New content...'); } </script><span style="font-size: 14px; text-align: justify;"> </span>
Dacă scriem codul JavaScript într-un fişier separat pe care îl implementăm în document, înseamnă
că funcţia noastră myFunction nu îi va deranja pe designeri şi pe ceilalţi colaboratori cu care lucrăm
împreună la proiect. Totuşi, am separat funcţia într-un fişier extern şi am ascuns-o puțin de
colaboratorii noştri care se ocupă de structura paginii, pentru ca aceștia să nu fie deranjați de codul
JavaScript în timpul activității lor. Dar acest document posedă în continuare atributul onclick, care
conţine apelul JavaScript al funcţiei. Trendul aşa-numitului „JavaScript discret” presupune că şi
acest atribut este înlăturat de pe documentul HTML şi că ascultarea evenimentului se efectuează
din JavaScript, iar tag-urile nu sunt suprasolicitate. Deci, așa cum am separat stilizarea de structură
(HTML de CSS), şi JavaScript trebuie să se separe de HTML. Despre metodele care ne vor permite
să facem acest lucru vom discuta puțin mai târziu în lecţie.
Am menţionat şi am folosit unul dintre cei mai frecvenţi ascultători de evenimente/ eventlisteners
– onclick. Însă, pe lângă clic există şi eventlisteners care se vor activa atunci când:
se finalizează încărcarea paginii web sau a imaginii (onload);
cursorul mouse-ului se află deasupra elementului (onmouseover);
cursorul mouse-ului părăseşte câmpul elementului (onmouseout);
se modifică câmpul input (onchange);
formularul este submit (onsubmit);
se apasă o tastă de pe tastatură (onkeypress, onkeydown);
se eliberează o tastă de pe tastatură (onkeyup);
se resetează formularul (onreset).
Deoarece lista de evenimente care se pot înregistra este destul de mare, aici nu vom analiza fiecare
eveniment în parte, dar prin câteva exemple vom demonstra cum funcţionează cele mai importante.
Exemplu de eveniment onchange
Acest eveniment se activează atunci când se modifică elementul.
162
Să vedem exemplul:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html> <body>
<select onchange="changeFunc()"> <option>Opel</option> <option>Fiat</option> <option>Mercedes</option> </select>
<p id="p_1"></p> <script> function changeFunc(){ alert('X is selected.'); } </script> </body> </html><span style="font-size: 14px; text-align: justify;"> </span>
La fel ca oricare alt atribut al evenimentului, şi onchange se poate scrie ca atribut al elementului
HTML. În cazul nostru, HTML este selectat cu trei opţiuni posibile la alegere (Opel, Fiat şi
Mercedes). În momentul în care are loc modificarea în opțiunea selectată, va fi activat evenimentul
onchange, care apelează funcţia changeFunc(). În cadrul funcţiei changeFunction(), se află
umătoarea linie de cod:
1 alert('X is selected.');<span style="font-size: 14px; text-align:
justify;"> </span>
ceea ce înseamnă că fereastra pop-up va fi afișată de fiecare dată când utilizatorul modifică
selecţia.
Observaţi că pentru fiecare element selectat se scrie acelaşi mesaj: X is selected. Să încercăm acum
să ne îmbunătăţim exemplul astfel încât să apară mesajul: marca_automobilului is selected.
Să vedem exemplul care rezolvă această problemă:
1
2
3
4
5
6
7
8
<html> <body>
<select onchange="changeFunc(this.value)"> <option>Opel</option> <option>Fiat</option> <option>Mercedes</option> </select>
163
9
10
11
12
13
14
15
16
17
18
19
<p id="p_1"></p> <script> function changeFunc(car){ alert(car + ' is selected.'); } </script> </body> </html><span style="font-size: 14px; text-align: justify;"> </span>
Dacă priviţi codul cu atenţie, veţi vedea că în comparație cu exemplul precedent modificările sunt
minime, mai exact deosebirea constă numai în parametrul funcţiei. La înregistrarea evenimentului
onchange, se apelează funcţia changeFunc, căreia îi trimitem un parametru. Parametrul este:
this.value. La distribuire, folosim cuvântul-cheie this şi îl tratăm ca un obiect. Acum este important
de ştiut că acest cuvânt reprezintă obiectul asupra căruia este apelat, iar când ne amintim de bazele
funcţionării lui DOM, devine clar că şi select tag este obiect. Aceasta înseamnă că în cazul nostru
this este, de fapt, select tag, dar prezentat ca un obiect. Deoarece select tag are propria sa valoare,
şi obiectul reprezentărilor acestui tag are o proprietate care reprezintă această valoare (value). La
final, concluzionăm că, atunci când scriem this.value, obţinem de fapt valoarea din select tag.
Acest string se distribuie ca parametru funcţiei changeFunc(). De exemplu, când utilizatorul
selectează opțiunea Fiat, va avea loc evenimentul onchange şi va fi apelată funcţia ca şi când am
fi scris:
1 changeFunc(‘Fiat’);<span style="font-size: 14px; text-align:
justify;"> </span>
Deoarece ca argument al funcţiei este marcat identificatorul car, în corpul funcţiei se va executa
codul:
1 alert(car + ' is selected.');<span style="font-size: 14px; text-align:
justify;"> </span>
în timp ce în cazul în care utilizatorul a ales Fiat, această linie de cod va da acelaşi rezultat ca şi
când am fi scris:
1 alert('Fiat is selected.');<span style="font-size: 14px; text-align:
justify;"> </span>
Un efect similar se poate obţine şi altfel:
1
2
3
4
5
<html> <body> <select onchange="changeFunc(this)"> <option>Opel</option> <option>Fiat</option>
164
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<option>Mercedes</option> </select>
<p id="p_1"></p> <script> function changeFunc(car){ var x = car.value; alert(x + ' is selected.'); } </script>
</body> </html><span style="font-size: 14px; text-align: justify;"> </span>
Deosebirea dintre aceste două moduri constă în faptul că, în primul rând, îi trimitem funcţiei o
singură valoare de care se poate ocupa, în timp ce în cealaltă funcţie trimitem întregul obiect (this).
Al doilea mod este util foarte des, deoarece de la obiect putem să obţinem şi alte informaţii, nu
doar proprietatea value. Deoarece funcţiei îi este distribuit întregul obiect, iar noi avem nevoie de
proprietatea value, creăm variabila locală x şi îi atribuim valoarea: car.value, după care punem
variabila x în alert().
Pentru a înţelege şi mai bine modul în care se poate folosi cuvântul-cheie this, să vedem următorul
caz.
În exemplul următor, observăm că nu există atribute id ale tag-urilor div, precum şi că tag-urile div
se deosebesc numai după conţinut, în timp ce apelurile sunt identice:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html> <head> <title>DOM</title> </head> <body> <script> function clickFunction(obj){ alert(obj.innerHTML); } </script> <div onclick="clickFunction(this)">Text 1</div> <div onclick="clickFunction(this)">Text 2</div> <div onclick="clickFunction(this)">Text 3</div>
</body> </html><span style="font-size: 14px; text-align: justify;"> </span>
165
18
În cadrul fiecărui apel al funcţiei, distribuim contextul cu cuvântul-cheie this. Astfel, îi transmitem
lui JavaScript să lucreze tocmai cu acest obiect distribuit. Cu aceasta distribuim obiectul de pe
pagină, cu care JavaScript va executa anumite comenzi definite cu funcţia clickFunction().
În momentul în care provocăm un eveniment, JavaScript realizează automat şi obiectul de tip
Event, în care plasează diferiţi parametri legaţi de acest eveniment. De exemplu, care a fost poziţia
cursorului în momentul evenimentului, tipul evenimentului (clic, apăsarea tastei), obiectul care a
provocat evenimentul. Unele dintre aceste informaţii pot fi foarte importante, de exemplu când
vrem să manipulăm câmpurile de introducere a textului şi când vrem să urmărim fiecare pas al
introducerii:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html> <head> <title>DOM</title> </head> <body> <script type="text/javascript"> function displayunicode(e){ var unicode = e.keyCode ? e.keyCode : e.charCode alert(unicode) } </script>
<form> <input type="text" size="2" maxlength="1" onkeyup="displayunicode(event); this.select()" /> </form> </body> </html><span style="font-size: 14px; text-align: justify;"> </span>
Acest exemplu însoțește fiecare caracter introdus în caseta de text şi afișează alert cu Unicode
pentru tastă. Deoarece atributele pentru manipularea evenimentelor acceptă codul JavaScript,
avem posibilitatea să apelăm mai multe funcţii sau chiar să scriem un cod mai lung (lucru care
deseori nu este vizibil şi trebuie evitat), dar afirmaţiile trebuie separate prin semnul ; , la fel cum
am făcut şi aici. În primul rând, se apelează funcţia definită de utilizator displayunicode(event)
care afișează ferestra alert(), apoi se apelează şi metoda select():
1 this.select()<span style="font-size: 14px; text-align: justify;"> </span>
ceea ce determină selectarea textului în câmpul input, astfel încât după confirmarea lui alert(),
utilizatorul să poată să introducă imediat un caracter nou în câmp. Deseori, această metodă poate
fi utilă în timpul validării, când utilizatorul trebuie să editeze conţinutul unui câmp din cauza
intrării care nu a fost validă.
166
Evenimentul onload – manipularea sigură a lui DOM
Fişierele externe se încarcă cel mai des în secțiunea head a documentului, aşadar aici găsim şi
implementările fişierelor externe JavaScript. Deoarece această parte a documentului se află în
vârful paginii, adică deasupra părţii body, unde sunt plasate toate tag-urile care se afișează pe
pagină, înseamnă că JavaScript va fi apelat înainte ca întregul document să se încarce. În astfel de
situaţii, trebuie să avem mare grijă.
Să vedem ilustraţia:
Imaginea 17.2.
În această ilustraţie avem un exemplu clasic de organizare greșită a codului. Linia roşie reprezintă
o parte din document, care se încarcă până în momentul apelării fişierului extern script.js. În
script.js (dreapta), se află codul care încearcă să acceseze elementul care posedă valoarea ID a
atributului „id_1”, însă este verificată numai partea încărcată a documentului (prezentată cu
săgeata roşie), motiv pentru care tag-ul p căutat nu este găsit. În consolă, apare eroarea aşteptată:
Imaginea 17.3.
Cum rezolvăm această problemă?
167
Primul şi cel mai uşor mod este să mutăm implementarea fişierului script.js în partea de jos a
documentului, asigurând astfel încărcarea tuturor tag-urilor.
Totuşi, aceasta nu este cea mai bună soluţie. Recomandarea noastră este ca toate fişierele externe
js şi css să fie încărcate în partea head, pentru ca implementările să fie transparente. Cum să
păstrăm atunci implementarea în partea head şi în acelaşi timp să asigurăm încărcarea tuturor tag-
urilor în document? Aici intră în scenă evenimentul onload.
Asupra tag-ului body putem să definim acest eveniment şi să asigurăm apelarea funcţiei (să zicem
că această funcţie se numeşte start() ), care se va efectua prin manipularea DOM.
Acum, index.html din ilustraţia precedentă arată astfel:
1
2
3
4
5
6
7
8
9
<html> <head> <title>DOM</title> <script src="script.js"></script> </head> <body onload="start()"> <p id="id_1">Old text</p> </body> </html><span style="font-size: 14px; text-align: justify;"> </span>
La final, mai rămâne doar să încercuim cu funcţia start(). partea codului în fişierul .js .
Acum, fişierul nostru script.js va arăta astfel:
1
2
3
4
5
function start(){ var p1 = document.getElementById("id_1"); p1.innerHTML = "New text!";
}<span style="font-size: 14px; text-align: justify;"> </span>
Codul scris în acest fel ne asigură securitate când pregătim documentul pentru manipularea prin
DOM.
Validarea
Unitate: 18 din 19 00:32:36
+Rezumat
În această lecţie, nu punem accentul pe tehnici noi, ci pe cum să utilizăm într-un context special
ceea ce am învăţat până acum. Acest context este cel al validării controalelor de intrare.
168
Pentru a înţelege problema, trebuie să vedem modul în care controalele de intrare funcţionează şi
rolul lor într-o aplicaţie web.
În primul rând, controalele de intrare sunt singurele puncte prin care utilizatorul poate introduce
unele informaţii în aplicaţie. Prin urmare, dacă undeva pe pagină există un text box (de exemplu,
pentru numele de utilizator sau pentru parolă), utilizatorul trebuie să introducă aici o anumită
valoare. Apoi, această valoare se transmite codului de server care este procesată în funcţie de
context. În cazul în care utilizatorul introduce o valoare al cărui format nu corespunde sistemului
care procesează aceste valori, pot apărea probleme. Cu alte cuvinte, controalele de intrare sunt cea
mai slabă verigă a unei aplicaţii web, deoarece acestea sunt lăsate după bunul plac al utilizatorului.
De obicei, problemele cauzate de o inserare nepotrivită se rezolvă prin validarea pe partea de
server, dar acest proces poate fi uneori lent, deoarece utilizatorul trebuie să aştepte ca datele să
ajungă pe server şi să fie verificate. Dacă există mai multe controale, în codul de server trebuie
creat un mecanism care să returneze toate controalele valide pentru ca utilizatorul să nu fie nevoit
să introducă de fiecare dată acelaşi lucru. Validarea pe partea de client a fost şi principalul motiv
al apariţiei JavaScript. În acest mod serverele şi traficul nu se mai supraîncarcă, iar utilizatorilor li
se asigură o validare mai rapidă şi o navigare cât mai plăcută pe site.
De aceea, o practică bună este ca validarea să se efectueze şi pe partea de client a aplicaţiei, pentru
a preîntâmpina erorile înainte ca informaţiile să ajungă la server. Bineînţeles, nu trebuie să ne
bazăm în totalitate pe validarea efectuată pe partea de client. Rolul principal trebuie să-l aibă în
continuare validarea de server. Aşa cum JavaScript se execută pe calculatorul utilizatorului, astfel
acesta deţine controlul. În orice moment, utilizatorul poate dezactiva JavaScript în motorul său de
căutare sau poate modifica codul JavaScript, în aşa fel încât această validare să nu aibă nicio formă
de securitate. Validarea pe partea de client serveşte doar pentru a ajuta utilizatorul în timpul
anumitor inserări care nu sunt valide şi pentru a accelera inserarea validă, ceea ce implică interes
atât din partea utilizatorului cât şi din partea serverului.
Notă
Deşi validarea se execută pe partea de client, aceasta nu reprezintă un sistem de protecţie pe care
puteți să vă bazaţi în ceea ce privește securitatea, aşadar validarea pe server este obligatorie.
Când vorbim despre validarea unui control, putem observa două unităţi logice: prima se referă la
evenimentele de introducere a datelor în control şi a doua, la verificarea acestora. Ca să putem
efectua validarea datelor, avem nevoie de un anumit formular HTML din care să preluăm datele.
De obicei, în evenimentele formularului apelăm o anumită funcţie care execută validarea intrării
efectuate de utilizator. Trebuie să inițiem o anumită interacţiune cu utilizatorul, să-i oferim
posibilitatea să introducă singur datele care apoi trebuie verificate. Pentru început, vom crea un
formular gol. Aceasta se poate realiza în felul următor:
1
2
<html>
<head>
<title>Form</title>
169
3
4
5
6
7
8
</head>
<body>
<form name="myForm">
</body>
</html>
Acum, în acest formular putem adăuga anumite elemente. De exemplu, putem adăuga două
câmpuri de text şi un buton:
1
2
3
4
5
6
7
8
9
10
11
12
<html>
<head>
<title>Form</title>
</head>
<body>
<form name="myForm">
<input type="text" name="text1"/>
<input type="text" name="text2"/>
<input type="submit" value="Click"/>
</form>
</body>
</html>
După cum putem vedea, formularul poate să conţină multe elemente. Unele dintre aceste elemente
încep cu tagul input, care, după cum îi spune şi numele, reprezintă elementele care vor accepta o
anumită intrare/un anumit input de la utilizator. În momentul definirii acestor elemente, trebuie să
menţionăm tipul pe care îl dorim, folosind cuvântul cheie type. Pentru câmpurile de text folosim
tipul text, iar pentru buton, folosim submit. Pe lângă aceste atribute, butonul mai conţine şi
atributul value, care reprezintă textul de pe buton care va fi afişat în browserele web.
170
În continuare, vom vedea cum putem efectua verificarea datelor introduse. Nu vrem ca utilizatorul
să introducă valori goale sau alte valori inacceptabile. De aceea, după cum am spus deja, trebuie
să executăm validarea datelor. În timpul validării datelor pe partea de client, rolul cheie îl deține
JavaScript. Pentru a efectua verificările menţionate, avem nevoie de evenimente. Noi vrem să
activăm verificarea datelor din momentul în care utilizatorul dă submit formularului şi astfel
trimite datele.
Să vedem mai întâi modul în care putem procesa evenimentele de introducere a datelor în
controale:
1
2
3
4
<form onsubmit="return false">
<input type="text" name="user_name">
<input type="submit" value="Submit">
</form>
În acest formular observăm procesarea evenimentului onsubmit. Evenimentul trebuie să
returneze valoarea care va influenţa fluxul ulterior al formularului, de aceea în faţa numelui
valorii se află cuvântul return. În acest caz, formularul nu va fi transmis către server, deoarece
ca răspuns a fost transmisă valoarea false.
În loc de valoarea statică false, am putea atribui şi rezultatul unei funcţii (care returnează
valoarea boolean). Acestei funcţii i-am putea atribui întregul formular ca parametru.
De exemplu:
1
2
3
4
5
6
7
8
9
10
<html>
<head>
<title>Form</title>
</head>
<body>
<form name="myForm" onsubmit="return validateForm(this)">
<input type="text" name="user_name" placeholder="User name"/><br/>
<input type="password" name="password" placeholder="Password"/><br/>
<input type="submit" value="Click"/>
</form>
171
11
12
13
14
15
16
17
18
19
20
21
<script>
function validateForm(f){
alert(f.user_name.value + "\n" + f.password.value);
return true;
}
</script>
</body>
</html>
Primul lucru pe care îl observăm este că, în loc de valoarea false, se folosește funcţia JavaScript
validateForm() căreia, ca parametru, i-a fost transmis formularul (this). Dacă analizăm funcţia,
vom vedea că întreaga sa logică este alcătuită din doar două linii de cod. Prima linie este metoda
alert(), unde folosim proprietăţile:
f.user_name.value şi f.password.value
În acest mod accesăm valorile pe care le-a introdus utilizatorul în câmpurile input. În primul rând
accesăm formularul transmis (f) ca unui obiect, apoi specificăm numele câmpului input (vezi lecţia
Manipularea obiectelor HTML) și la sfârşit specificăm proprietatea value.
A doua linie de cod este: return false; cu care, de fapt returnăm valoarea boolean în locul din care
funcţia a fost apelată. Returnarea valorii boolean în locul din care a fost apelat evenimentul
onsubmit este foarte utilă deoarece, în funcţie de această valoare (dacă este true sau false), se va
lua decizia referitoare la transmiterea formularului pe server. Fiindcă aici vorbim despre validare,
o putem folosi astfel: introducem şi verificăm în funcţie câmpurile pe care le-a completat
utilizatorul, le verificăm valoarea, respectiv executăm validarea iar la sfârşit (dacă validarea este
corectă), returnăm valoarea true sau false (în caz că utilizatorul nu a completat în mod adecvat
câmpurile).
Definirea atributului action
172
Dacă funcţia definită la atributul onsubmit returnează valoarea boolean true, aceasta înseamnă că
datele au fost inserate corect în formular şi pot fi transmise serverului pentru validarea finală şi
manipularea ulterioară. După cum atributului onsubmit îi specificăm funcţia JavaScript care se
ocupă de validare, tot aşa şi atributului action trebuie să îi specificăm calea până la scriptul de
server care va prelua datele din formular. Ca să transmitem aceste date serverului putem folosi
metodele POST sau GET. Având în vedere că traficul de pe relaţia client-server are sens numai
dacă pe server există un script care să preia datele transmise, nu vom aprofunda aici aceste metode,
ci vom menţiona doar caracteristicile lor de bază.
Metoda GET
Aceasta are ataşată adresa la care se află răspunsul dorit. Totuşi, pe lângă adresă, cererea mai poate
să conţină şi anumiţi parametri pe care serverul este capabil să-i distingă, ceea ce înseamnă că şi
programatorul îi poate folosi în codul de server.
Parametrii trimişi prin metoda GET nu sunt deloc siguri, deoarece se emit în Query String (stringul
care reprezintă adresa completă a paginii). De aceea, de obicei parametri GET se criptează.
De exemplu:
www.mysite.com/index.html?id=098f6bcd4621d373cade4e832627b4f6
După semnul întrebării (?) specificăm parametrii transmişi prin metoda GET, aşadar această parte
se numeşte „parte parametrizată”. În cazul nostru, acesta este parametrul id cu valoarea:
098f6bcd4621d373cade4e832627b4f6. Prin metoda GET putem transmite un număr mai mare de
parametri, separându-i prin semnul &. De exemplu:
index.html?id=10&a=5&x=15
În acest fel nu transmitem niciun fel de informaţii vitale pentru securitate. Un astfel de cod este,
de obicei, reprezentarea codificată a unei părţi a sursei de date unde se află anumite informaţii.
Abia de aici încolo putem efectua verificările serioase (de exemplu, verificarea utilizatorului). Cu
toate acestea, chiar dacă se desfăşoară astfel, transmiterea datelor importante prin Query String
este nesigură şi nu o recomandăm. Un alt dezavantaj este că nu putem transmite o cantitate mare
de informaţii.
Aceasta nu înseamnă că trebuie să evităm Query String când transmitem informaţii. Îl putem
utiliza când este vorba de informaţii care nu au un context de securitate.
De exemplu:
173
www.mysite.com/index.html?product=15
În acest caz, trimiterea datelor prin Query String este adecvată, deoarece un utilizator maliţios nu
ar putea să facă nimic rău aplicaţiei dacă va tasta un număr greşit al produsului (cu excepţia faptului
că va ajunge la un alt produs decât cel dorit), iar linkul este lizibil şi funcţional. Desigur, în mod
obligatoriu toate abaterile de la scenariul dorit trebuie prelucrate în cod.
Metoda POST
Metoda POST funcţionează puţin diferit decât metoda GET, însă din punct de vedere al securităţii
se află la un nivel mai înalt. Mai exact, în momentul trimiterii cererii către server, dacă cererea
apelează această metodă, în conţinutul cererii se va afla şi un set de date serializate pe care serverul,
respectiv aplicaţia de pe server, le poate prelua pentru procesare. Informaţiile transmise pe această
cale nu pot fi văzute cu ochiul liber, însă datele transportate pot fi obţinute cu uşurinţă prin
verificarea codului HTML sursă al paginii.
Acest mod de trimitere a datelor se foloseşte de obicei pentru aplicaţiile în care se procesează
controale (formulare). Nu este recomandat pentru promovarea unei anumite pagini web, deoarece
nu poate fi trimisă numai adresa paginii (nu va da rezultate fără datele pe care le solicită). Pentru
a trimite aceste date, avem nevoie de un formular care le va serializa şi le va trimite.
Fiindcă procesarea ulterioară a acestor date pe server necesită cunoștințe despre tehnologiile de
server, nu vom intra în domeniul serverulului, ci vom rămâne în mediul de funcţionare a
JavaScript-ului. De asemenea, în atributul action vom scrie codul JavaScript pentru simularea
recepţionării datelor pe partea de server (în general, aici se inserează întotdeauna linkul către PHP
sau către un alt fişier pe server). Efectuăm acest lucru în felul următor:
action="javascript: spaţiu pentru codul JS"
Vom analiza acum un exemplu de validare care, doar în cazul în care câmpul user_name este
„James”, iar câmpul password este „James100”, va returna true la onsubmit şi va activa conţinutul
atributului action.
1
2
3
4
5
6
<html>
<head>
<title>Form</title>
</head>
<body>
174
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<form name="myForm" action="javascript: alert('Form is submitted')" onsubmit="return validateForm(this)">
<input type="text" name="user_name" placeholder="User name"/><br/>
<input type="password" name="password" placeholder="Password"/><br/>
<input type="submit" value="Click"/>
</form>
<script>
function validateForm(f){
if (f.user_name.value == "James" && f.password.value == "James100") {
return true;
}else{
return false;
}
}
</script>
</body>
</html>
În timpul apelării funcţiei, se activează ramificarea condiţionată a codului. Dacă toate condiţiile
pentru if sunt îndeplinite, va fi returnată valoarea true şi activat alert(), specificat în atributul action
al formularului. Pe de altă parte, dacă nu există suprapuneri, respectiv dacă condiţia nu este
îndeplinită, se va executa un bloc de cod (else) alternativ, aşadar nici activarea metodei (alert) în
atributul action nu va exista.
Notă
Acesta este doar un exemplu de validare care explică procesul prin username şi password, însă
atât acestea, cât şi restul informaţiilor care trebuie ascunse de utilizator, nu se scriu niciodată în
codul JavaScript.
175
De asemenea, utilizatorului îi putem oferi şi informaţii suplimentare. De exemplu, ce se întâmplă
dacă formularul nu este acceptat, ce parametri au fost introduşi greşit etc. În acest scop putem
folosi funcţia JavaScrip alert(), încorporată care trimite notificări utilizatorului, după cum putem
vedea şi în exemplul de mai jos. În afară de aceasta, putem folosi şi alte stiluri CSS pentru a
informa utilizatorul despre câmpurile incorecte. În exemplu am folosit stilul JavaScript numit
borderColor cu care, cu ajutorul lui CSS, putem colora marginile obiectului în culoarea dorită. În
exemplu, colorăm câmpul textual cu roşu, pentru ca utilizatorul să observe mai clar câmpul din
formular în care a inserat ceva greşit.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<html>
<head>
<title>Form</title>
</head>
<body>
<form name="myForm" action="javascript: alert('Form is submitted')" onsubmit="return validateForm(this)">
<input type="text" name="user_name" placeholder="User name"/>
<input type="submit" value="Click"/>
</form>
<script>
function validateForm(f){
if (f.user_name.value != "") {
return true;
}else{
f.user_name.style.borderColor = "red";
return false;
}
}
</script>
</body>
</html>
176
În acest mod putem procesa toate controalele unui formular, însă doar la nivelul
validării/confirmării formularului. Dacă avem nevoie de un nivel mai înalt de dinamism, ar trebui
să accesăm nivelul controalelor. Unul dintre modurile prin care putem face acest lucru este să
alegem evenimentul onblur al controalelor. Ştim că evenimentul onblur se activează în momentul
în care ieşim din control. Aceasta înseamnă că am fi putut să folosim funcţia ca event handler şi
să executăm în ea validarea controlului.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<html>
<head>
<title>Form</title>
</head>
<body>
<form name="myForm">
<label for="text1">First Name:</label><br/>
<input type="text" onblur="validateText(this)" name="text1"/><br/>
<label for="text1">Last Name:</label><br/>
<input type="text" onblur="validateText(this)" name="text2"/><br/>
<label for="text1">Telephone:</label><br/>
<input type="text" onblur="validateText(this)" name="text3"/><br/>
<input type="submit" value="Click"/>
</form>
<script>
function validateText(f){
if (f.value == "") {
f.style.borderColor = "red";
}else{
f.style.borderColor = "";
}
}
</script>
177
25
26
27
28
</body>
</html>
Dacă în acest caz ieşim din box-ul activ și în plus, în câmp nu este inserată nicio valoare, JavaScript
va schimba proprietatea borderColor şi îi va atribui valoarea red. Dacă utilizatorul revine la
câmpul respectiv şi îl completează cu anumite date, borderul roşu va fi eliminat prin codul else.
Dezavantajul acestei abordări este că necesită procesarea specială a fiecărui control în parte.
Dacă niciuna din aceste două abordări nu ne oferă un grad suficient de dinamică asupra
controalelor, putem face un pas înainte şi procesa controlul înainte ca utilizatorul să iasă din el.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html>
<head>
<title>Form</title>
</head>
<body>
<form name="myForm">
<label for="text1">First Name:</label><br/>
<input type="text" onkeyup="validateText(this)" name="text1"/><br/>
<label for="text1">Last Name:</label><br/>
<input type="text" onkeyup="validateText(this)" name="text2"/><br/>
<label for="text1">Telephone:</label><br/>
<input type="text" onkeyup="validateText(this)" name="text3"/><br/>
<input type="submit" value="Click"/>
</form>
<script>
function validateText(f){
if (f.value == "") {
178
18
19
20
21
22
23
24
25
26
27
28
29
f.style.borderColor = "red";
f.focus();
}else{
f.style.borderColor = "";
}
}
</script>
</body>
</html>
Validarea va fi executată în momentul în care eliberăm tasta de pe tastatură, iar dacă utilizatorul
inserează o valoare, pe pagină nu vor apărea schimbări, în timp ce dacă utilizatorul şterge toate
literele, câmpul se va colora cu roşu. Poate că acest lucru nu are prea mult sens în ceea ce privește
validarea, dacă în câmp există o intrare. Dar, de exemplu, dacă pe site-ul nostru există o limită care
nu permite ca valoarea câmpurilor să fie mai mică de 5 caractere/litere, atunci codul ar putea să
arate astfel:
1
2
3
4
5
6
7
8
9
<html>
<head>
<title>Form</title>
</head>
<body>
<form name="myForm">
<label for="text1">First Name:</label><br/>
<input type="text" onkeyup="validateText(this)" name="text1"/><br/>
<label for="text1">Last Name:</label><br/>
179
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<input type="text" onkeyup="validateText(this)" name="text2"/><br/>
<input type="submit" value="Click"/>
</form>
<script>
function validateText(f){
if (f.value.length < 5) {
f.style.borderColor = "red";
f.focus();
}else{
f.style.borderColor = "";
}
}
</script>
</body>
</html>
Inserarea numerelor/cifrelor
Dacă vrem să fim siguri că utilizatorul va introduce doar numere, creăm un string care posedă toate
cifrele şi punctul. În timpul validării, am fi trecut prin fiecare caracter pe care utilizatorul trebuie
să-l insereze şi am fi verificat dacă fiecare caracter poate fi găsit în acest string. Dacă caracterul
căutat este găsit, deci dacă este vorba de o cifră sau un punct, metoda indexOf() va returna indexul
pe care se găseşte cifra respectivă în string. În caz contrar, va fi returnată valoarea -1.
Haideţi să vedem un exemplu.
1
2
<html>
180
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<head>
<title>Form</title>
</head>
<body>
<form name="myForm">
<label for="text1">Telephone:</label><br/>
<input type="text" onkeyup="validateText(this)" name="text1"/><br/>
<input type="submit" value="Click"/>
</form>
<script>
function validateText(f){
var str = " 0123456789.";
var num = true;
var c;
for (i = 0; i < f.value.length && num == true; i++){
c = f.value.charAt(i);
if (str.indexOf(c) == -1)
num = false;
}
if(!num){
f.style.borderColor = "red";
}else{
f.style.borderColor = "";
}
}
</script>
</body>
</html>
181
31
32
33
De asemenea, se poate să nu vrem să comunicăm cu utilizatorul, ci să curăţăm în mod automat
inserarea sa inadecvată.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<html>
<head>
<title>Form</title>
</head>
<body>
<form name="myForm">
<label for="text1">Telephone:</label><br/>
<input type="text" onkeyup="validateText(this)" name="text1"/><br/>
<input type="submit" value="Click"/>
</form>
<script>
function validateText(f){
var str = " 0123456789.";
var c;
for (i = 0; i < f.value.length; i++){
c = f.value.charAt(i);
if (str.indexOf(c) == -1){
f.value = f.value.replace(c,"");
}
}
182
21
22
23
24
25
26
27
}
</script>
</body>
</html>
Expresii regulate
Cel mai bun mod de a valida o înregistrare sub formă de text este prin utilizarea expresiilor
regulate, iar acestea sunt exact modelele după care testăm sau formăm această înregistrare. Deşi
foarte puternice, expresiile regulate pot fi inconvenabile în uz, deoarece erorile se omit foarte uşor.
Să vedem acum un exemplu de validare a unei adrese de e-mail cu ajutorul expresiilor regulate.
1
2
3
4
5
6
7
8
9
10
11
12
<html>
<head>
<title>Form</title>
</head>
<body>
<form name="myForm">
<label for="text1">E-mail:</label><br/>
<input type="text" onblur="validateText(this)" name="text1"/><br/>
<input type="submit" value="Click"/>
</form>
<script>
183
13
14
15
16
17
18
19
20
21
22
23
24
25
function validateText(f){
var regEx = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-
9]{2,4})$/;
if(!f.value.match(regEx)){
alert("Incorrect Email");
}else{
alert("Correct!");
}
}
</script>
</body>
</html>
Setul complex de caractere atribuit în variabila regEx este de fapt expresia regulată. Întreaga
expresie este atribuită variabilei de tip String, apoi este apelată metoda String match(), care verifică
dacă există vreun String într-un alt String. Această metodă verifică dacă există vreo suprapunere,
şi dacă e așa, atunci returnează valoarea boolean true. În caz contrar va returna valoarea false.
Acum să vedem cum arată validarea inserării numerice cu ajutorul expresiilor regulate.
1
2
3
4
5
6
7
8
9
<html>
<head>
<title>Form</title>
</head>
<body>
<form name="myForm">
<label for="text1">Number:</label><br/>
<input type="text" onkeyup="validateText(this)" name="text1"/><br/>
<input type="submit" value="Click"/>
184
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</form>
<p></p>
<script>
function validateText(f){
var p = document.getElementsByTagName("p")[0];
var re=/^(\d|-)?(\d|,)*\.?\d*$/;
if(!f.value.match(re)){
p.innerHTML = "Incorrect!";
}else{
p.innerHTML = "Correct...";
}
}
</script>
</body>
</html>
Pe lângă manipularea obiectelor String, expresiile regulate pot avea şi propriul lor tip. (RegExp).
Atunci când le utilizăm, trebuie să le utilizăm şi metodele.
Pentru a obţine, cu ajutorul obiectului RegExp, acelaşi efect ca şi când am folosi funcţia String
match, trebuie să folosim metoda exec() care, în calitate de parametru, primeşte Stringul care
trebuie testat. Iată şi funcţia pentru testarea e-mailului, efectuată cu ajutorul obiectului RegExp.
1
2
3
4
<html>
<head>
<title>Form</title>
</head>
185
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<body>
<form name="myForm">
<label for="text1">Number:</label><br/>
<input type="text" onkeyup="validateText(this)" name="text1"/><br/>
<input type="submit" value="Click"/>
</form>
<p></p>
<script>
function validateText(f){
var p = document.getElementsByTagName("p")[0];
var re=new RegExp(/^(\d|-)?(\d|,)*\.?\d*$/);
if(!re.exec(f.value)){
p.innerHTML = "Incorrect!";
}else{
p.innerHTML = "Correct...";
}
}
</script>
</body>
</html>
Notă
În timpul iniţializării (fie prin obiect, fie prin string), expresiile regulate nu trebuie puse între
ghilimele, ci trebuie începute şi încheiate cu linia oblică- Slash (/).
186
Cookies
Unitate: 19 din 19 00:17:37
+Rezumat
În această lecţie vom învăţa cum să manipulăm Cookie-urile. JavaScript nu este un limbaj de
programare de server şi nici tehnologie de server. De aceea nu este capabil să susţină preluarea
datelor de pe server, acțiune care necesită sesiuni şi parametri post (decât dacă se folosesc obiectele
HttpRequest, respectiv tehnologia AJAX).
Pe de altă parte, cu JavaScript putem citi valorile parametrilor GET şi ale Cookie-urilor. Cookie-
urile sunt date mici cu nume, salvate de browserul web şi ataşate unei anumite pagini web.
Datele Cookie se transmit automat între browserul web şi serverul web, astfel încât scripturile de
pe partea de server să poată citi şi scrie valorile care se salvează pe partea de client. Rolul principal
al Cookie-urilor este să salveze starea şi să stabilească o anumită identitate pentru browserul web
care le foloseşte.
Cookie-urile se pot accesa, seta şi şterge folosind opţiunile obiectului document. Pentru a face
acest lucru, trebuie să citiţi şi să scrieţi opţiunile Cookie pe obiectul document folosind stringuri
special formate în acest scop. Durata şi domeniul de vizibilitate a variabilelor Cookie pot fi setate
separat pentru fiecare Cookie în parte.
Din pricina notorietății utilizării lor, deseori puteţi întâlni cazuri în care Cookie-urile sunt
dezactivate la anumiţi clienţi. Acest lucru se întâmplă deoarece se pot folosi pentru a submina
informaţiile confidenţiale ale utilizatorului. De aceea, înainte de a lucra cu Cookie-urile, este de
preferat să verificaţi dacă acestea au fost activate. Puteți face acest lucru prin simpla apelare a
proprietăţii cookieEnabled astfel:
1
2
3
4
<script> var cookie=navigator.cookieEnabled; document.write(cookie); </script>
Dacă pe ecran apare true, înseamnă că lucrul cu Cookie-urile este permis. În caz contrar, dacă
apare valoarea false, înseamnă că lucrul cu Cookie-urile nu este posibil, deoarece ar trebui ca mai
întâi să fie activate de către utilizator.
Inserarea şi citirea parametrilor din Cookie-uri
Pe lângă nume şi valoare, fiecare Cookie mai poate conține atribute opţionale care îi controlează
durata şi volumul. Valorile care se păstrează în Cookie-uri sunt temporare şi, de obicei, durează
187
atâta timp cât își ține deschis utilizatorul final browserul web. Deoarece Cookie-urile nu se află în
câmpul de vizibilitate al unei singure ferestre, durata lor depinde de întregul proces al browserului
web şi de durata acestuia. Dacă vrem ca un Cookie să dureze şi după ce închidem browserul web,
trebuie să găsim un mod de a-i spune acestuia cât timp vrem ca un Cookie să păstreze o valoare pe
care am definit-o. Efectuăm aceasta definind atributul expires, pe care îl vom exemplifica puțin
mai încolo. Dacă definim durata valorii unui Cookie, browserul web va salva această valoare într-
un anumit fişier, care va fi şters după expirarea timpului definit.
De asemenea, trebuie să ştim cum putem defini valorile în Cookie. Regula este ca fiecare Cookie
să fie alcătuit din perechi de chei şi valori. Este important să respectăm următoarea ordine:
1 key-value; expiration_date; path; domain;
Desigur, nu toate atributele sunt obligatorii, dar se subînţelege că dacă creăm un Cookie, vrem să
salvaţi anumite valori în el. Primul atribut se referă la cheie şi valoare. De exemplu, perechea
cheie-valoare o putem defini în felul următor:
1 userVisits=7;
Cheia este userVisits, iar valoarea este 7. Ca să obţinem conţinutul unui anumit Cookie, mai întâi
trebuie să-l definim.
<script>
var new_cookie=document.cookie;
new_cookie= "userVisits=7;";
var cookie = new_cookie.split("=");
var name= cookie[0];
var value = decodeURI(cookie[1]);
document.write(name+" " + value);
</script>
În acest exemplu vă vom explica în detaliu întregul procedeu de creare şi scriere a unui Cookie.
Mai întâi, definim variabila care va reprezenta Cookie-ul nostru. Cookie-ul se defineşte prin
intermediul obiectului document. Valorile pe care Cookie-ul le conţine se definesc într-un string.
În exemplul nostru, pentru început nu am definit niciun fel de atribute suplimentare, ci doar
atributul cheie-valoare. Apoi, folosim funcţia split(), care împarte stringul după un anumit
parametru. Rezultatul executării acestei metode, pe care am explicat-o în detaliu în lecţiile
precedente, este un şir. Astfel, în exemplu avem două valori, una este cheia (în partea stângă a
semnului egal), iar a doua este valoarea (în partea dreaptă a semnului egal). Ca să obţinem
valoarea, folosim încă o funcţie decodeURI() fiindcă în Cookie-uri valorile sunt de obicei codate,
aşadar în acest mod acestea le traducem într-o formă comprehensibilă. În caz că metodei
decodeURI() îi transmitem un string „normal”, aceasta nu va executa nicio modificare. La final
188
scriem valoarea variabilei care conţine cheia şi valoarea, prin care obţinem scrierea Cookie-ului
pe pagină.
Acum, pe baza acestui exemplu, putem defini cu uşurinţă durata Cookie-ului, respectiv perioada
în care Cookie-ul va salva valoarea pe care o definim. În JavaScript, Cookie-ul se află în cadrul
obiectului document, în proprietatea Cookies. Ca să creăm Cookie-uri, avem nevoie de cel puţin
doi (trei) parametri. Cheia şi valoarea reprezintă primul parametru (de aici cifra trei dintre
paranteze), iar al doilea este data de expirare. Data de expirare este o componentă foarte
importantă, fiindcă în afara faptului că putem defini când vor expira Cookie-urile, o mai putem
folosi şi pentru a distruge Cookie-urile momentan active. Să vedem un exemplu.
var d = new Date();
d.setTime(d.getTime() + (3*24*60*60*1000));
În acest exemplu, în primul rând avem nevoie de obiectul de tip Date(). Acest obiect (timpul actual)
se foloseşte pentru construirea unui nou obiect de tip Date, însă de această dată ca o combinaţie
între timpul actual şi durata Cookie-ului. În a doua linie folosim metoda getTime() asupra
obiectului d pentru a obţine înregistrarea timpului actual în milisecunde (este vorba de o
înregistrare standardizată a timpului sub formă de număr, care reprezintă numărul de milisecunde
din data de 01.01.1970). Acestui număr îi adăugăm şi valoarea expresiei matematice:
3*24*60*60*1000 ca să obţinem numărul de milisecunde care va trece în 3 zile. Aici am putut să
calculăm valoarea şi manual, iar apoi am putut să scriem numărul de miliscunde, însă modul folosit
de noi este mai clar, iar modificările se fac mai uşor. După aceasta, timpul actual se adună cu
numărul în milisecunde obţinut şi astfel avem timpul exact al duratei Cookie-ului.
Apoi, trebuie să definim Cookie-ul introducând valorile dorite:
1 document.cookie="myCookie=myValue; expires=" + d.toUTCString();
După cum am putut vedea în exemplul precedent, crearea unui Cookie se face cu ajutorul unui
String.
În exemplu am folosit valori statice pentru denumirea Cookie-ului şi pentru valoarea sa, dar în
practică aceste două valori trebuie să fie parametrizate (la fel ca valoarea Expires). Parametrul
menţionat, Expires, reprezintă data de expirare a Cookie-ului (care trebuie să fie în format UTC sau
GMT, aşadar trebuie folosite funcţiile toUTCString() sau toGMTString()), pentru care vom pune
valoarea variabilei expirare/expire (care reprezintă un an de zile începând cu data de azi). Un
exemplu dinamic ar putea să arate astfel:
<script>
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires="+d.toUTCString();
document.cookie = cname + "=" + cvalue + "; " + expires;
189
}
</script>
Iar crearea Cookie-ului poate să arate astfel:
1 setCookie("username","James",1);
Aceasta este procedura completă pentru setarea unui Cookie. După pornirea acestui script, nu veţi
vedea niciun rezultat, deoarece Cookie-ul a fost doar definit, încă nu a fost scris. Dacă nu primim
nicio eroare, Cookie-ul va fi setat şi va putea fi vizibil până la expirarea perioadei definite. De
asemenea, va fi vizibil, nu numai din JavaScript, ci şi din scripturile de server (PHP).
Dacă nu setăm o limită de timp, Cookie-ul va fi valid până când aplicaţia client va fi închisă.
Ca să citim parametrii din Cookie, putem folosi o tehnologie asemănătoare cu cea utilizată când
citim un String URL. Având în vedere că toate cheile şi valorile unui Cookie se află într-un String
delimitat prin semnul ; este suficient să transformăm acest String într-un şir şi să căutăm elementul
de care avem nevoie, respectiv, care corespunde cheii căutate. În exemplul anterior, adăugăm
următorul cod:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function getCookie(cname) { var name = cname + "="; var ca = document.cookie.split(';'); for(var i=0; i<ca.length; i++) { var c = ca[i]; while (c.charAt(0)==' ') c = c.substring(1); if (c.indexOf(name) == 0){ var v = c.substring(name.length, c.length); alert(cname + " = " + v); return c.substring(v); } } return ""; }
Dacă vrem să ştergem un Cookie, acesta trebuie iniţializat din nou, dar cu timpul curent sau cel
de dinainte.
Bineînţeles, dacă am creat funcţia setCookie() în exemplul de mai sus, atunci putem face acest
lucru cu ajutorul ei:
1 setCookie ("username","James",-1);
În afara celor doi parametri menţionaţi, mai există şi alţi parametri opţionali pentru crearea
Cookie-ului, precum:
190
path
Dacă nu vrem să punem Cookie-ul în folderul implicit de pe disc, putem introduce un folder
alternativ prin acest parametru.
domain
Cookie-urile pot fi deschise doar de către domeniul care le-a creat. Ca parametru putem
introduce numele acestui domeniu.
secure
Dacă această opţiune este activată, Cookie-ul va putea fi citit şi creat doar prin intermediul
conexiunii SSL (protocolul https).
Citirea parametrilor din Stringul URL
Cunoaștem obiectul window şi proprietatea sa, obiectul location. Ne reamintim că acesta conţine
adresa completă a documentului (cea care este scrisă în Stringul URL). De asemenea, Location
posedă o proprietate numită search care conţine doar partea de interogare a Stringului URL
(fiecărei adrese din Stringul URL i se poate adăuga şi partea de interogare pe care o obţinem în
felul următor: după adresă punem semnul întrebării, iar apoi introducem perechile de chei şi valori
pentru parametri, separate prin semnul &.
De exemplu: http://www.example.com/index.html?id=5&x=30&y=50).
Ceea ce putem face este să căutăm manual întreaga parte de interogare, apoi să comparăm toţi
parametri cu cel de care avem nevoie şi a cărui valoare, dacă există, o vom atribui ca ieşire a
acestui proces.
1
2
3
4
5
6
7
8
9
10
<html> <head> <title>Cookies</title> </head> <body>
<script> function getParameter(p){ var paramStr=window.location.search.substring(1); var paramArr=paramStr.split("&"); rez = -1; for(i=0;i<paramArr.length;i++) {
191
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
if(paramArr[i].split("=")[0]==p) { rez = paramArr[i].split("=")[1]; break; } } return rez; } var p="id"; document.write("Parameter "+ p +" is " + getParameter(p)); </script> </body> </html>
Înainte de a ne ocupa de funcţia getParameter() să analizăm următoarele două linii de cod:
1
2
3
var p="id"; document.write("Parameter "+ p +" is " + getParameter(p)); <br><br>
Mai întâi, declarăm variabila p care reprezintă denumirea parametrului pe care îl căutăm (cheia).
Această valoare trebuie să fie variabilă şi să depindă de nevoile actuale ale aplicaţiei (aceasta
depinde de parametrul de care avem nevoie). Următoarea linie de cod reprezintă o simplă scriere
a denumirii parametrului şi a valorii acestuia pe ecran. Aici observăm şi apelarea funcţiei
getParameter() căreia îi transmitem variabila p.
Funcţia getParameter() manipulează un argument necesar în bucla for. Înainte de această buclă,
putem vedea trei linii de cod pe care le vom explica acum. Liniile de cod sunt:
1
2
3
var paramStr=window.location.search.substring(1); var paramArr=paramStr.split("&"); rez = -1;
paramStr reprezintă un string pe care îl obţinem atunci când apelăm proprietatea search asupra
obiectului document.location şi asupra acestuia apelăm apoi metoda substring(). Această
proprietate returnează o parte din adresa URL după semnul întrebării (?), şi acesta este spaţiul în
care se găsesc parametrii. Totuşi, în acest mod am fi obţinut un string cu semnul întrebării la
192
început, de care noi nu avem nevoie. De aceea, apelăm metoda substring() căreia îi transmitem ca
parametru numărul 1. Aceasta înseamnă că stringul va fi tăiat în aşa fel încât să se returneze partea
din string de pe poziţia cu indexul 1 până la sfârşitul stringului (deci, eliminăm semnul ?).
A doua variabilă paramArr devine şir după apelarea metodei split() asupra stringului paramStr.
Să ne reamintim că după eliminarea semnului întrebării, ne-au rămas doar parametrii separaţi prin
semnul &, pe care îl folosim aici ca separator pentru crearea elementelor în noul şir.
Acum cu bucla for trecem prin acest şir, însă înainte de aceasta trebuie să declarăm variabila rez
care posedă valoarea -1. Această valoare va fi returnată în cazul în care funcţiei i se solicită un
parametru inexistent. Aici ar putea fi specificat şi un alt rezultat, însă atunci când lipseşte un
rezultat al căutării, se returnează de obicei valoarea -1.
Ajungem şi la bucla care trece prin toţi membrii şirului paramArr. Asupra fiecărui element al
şirului apelăm metoda split() şi îi transmitem parametrul „=” ca să creăm un nou şir care trebuie
să posede doi membri. Primul este denumirea parametrului sau cheia şi are indexul 0, iar celălalt
este chiar valoarea şi are indexul 1. Dacă valoarea pe indexul 0 este egală cu argumentul funcţiei,
are loc o suprapunere, ceea ce înseamnă că am obţinut parametrul dorit şi că putem părăsi bucla
(break), iar variabila rez obţine valoarea pentru parametrul căutat:
1 rez = paramArr[i].split("=")[1];
Am părăsit bucla, așadar nu mai rămâne decât ca funcţia să returneze valoarea variabilei rez.
return rez;
La final, Cookie-urile, în afara cantităţii de date pe care o pot conţine (4k), mai au şi alte
restricţii. Nu putem pune mai mult de 20 de Cookie-uri pe un domeniu, iar browserul web nu poate
susţine mai mult de 300 de Cookie-uri (dacă se depășește acest număr, ultimul Cookie utilizat va
fi şters).
Notă
Cookie-urile au următoarele caracteristici pe care trebuie să le reţineţi:
nu suportă mari cantităţi de date (nu suportă mai mult de 4 kB de date);
au un timp de creare şi de expirare;
au informaţii despre domeniul de origine;
ideea de bază este deplasarea unei informaţii unice prin întreg domeniul.
Recommended