192
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ă

Core JavaScript Programming - mygarage.ro · Core JavaScript Programming Descrierea cursului Bazele programării JavaScript și programarea bazată pe limbajul C. Implementarea lui

  • Upload
    others

  • View
    150

  • Download
    3

Embed Size (px)

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

15

Imaginea 2.2.

Imaginea 2.3.

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.