Sunteți pe pagina 1din 22

Programare Web - Curs 3

Scurtă recapitulare – noțiuni de teorie prezentate în laboratoarele 1,2:

Un literal în JavaScript reprezintă o valoare pentru un tip specific,


precum un șir(String), număr în virgulă mobilă(Number), sau un boolean.

O primitivă în JavaScript este o instanță a unui anumit tip de dată. Există


5 astfel de tipuri de dată : String, Number, Boolean, null și undefined.
Doar la primele 3 dintre acestea există posibilitatea de a fi folosite
proprietăți și metode.

Putem crea primitive de tip boolean, string și number, prin folosirea


obiectului fără operatorul new (acestea sunt strict egale cu literalii,
deoarece primitivele sunt comparate prin valoare, iar valorile sunt
literali), în timp ce instanțele unui obiect nu.

Pentru a instanția un obiect se folosește operatorul new.

Diferența dintre o primitivă și o instanță a unui obiect se poate vedea


când se compară acestea folosind egalitatea strictă (===).

Pentru a verifica tipul de variabilă definită, se folosește typeof.

Metoda indexOf() are ca și prim parametru o valoare de căutat și


opțional ca și al doilea parametru un index de început.

Un vector gol reprezintă de fapt o pereche goală de paranteze pătrate


[ ]. Pentru a crea un vector cu valori, acestea se introduc între
parantezele pătrate, separate prin virgulă. Valorile individuale dintr-un
Programare Web - Curs 3

vector se numesc elemente sau itemi. Accesul la un element din vector


se face folosind indexul acestuia (numărul ce corespunde cu locul din
vector ce stochează o anumită valoare) între parantezele pătrate. Se
poate folosi indexul pentru a seta, schimba sau chiar a adăuga elemente
unui vector. Elementele unui vector nu trebuie să fie toate de același tip.

Proprietățile și metodele ne ajută în lucrul cu vectori. Proprietățile, în


general spun ceva despre vector, iar metodele, de obicei, fac ceva pentru
a schimba vectorul sau întorc un nou vector.

Proprietatea length de aflare a lungimii unui vector întoarce câte


elemente are vectorul. Valoarea ultimului index dintr-un vector poate fi
aflată prin lungimea vectorului minus o unitate.

Metoda push(element); reprezintă o metodă de adăugare de


elemente la finalul unui vector. Atunci când este apelată metoda
push(element) este adăugat elementul dintre paranteze la vector,
apoi este returnată noua lungime a vectorului.

Pentru a adăuga un element la începutul unui vector se utilizează


unshift(element);

Metoda pop(element); reprezintă o metodă de eliminare a ultimului


element al unui vector.
Programare Web - Curs 3

Pentru a elimina și returna primul element al unui vector se folosește


metoda shift(element);

Putem folosi unshift și shift pentru a adăuga și elimina itemi de la


începutul unui vector, la fel cum folosim push și pop pentru a adăuga și
elimina itemi de la finalul unui vector.

Pentru a aduna doi vectori pentru a face unul nou, se poate folosi
vector1.concat(vector2). Termenul concat este prescurtarea de la
concatenare. Metoda concat() va combina ambii vectori într-unul nou,
cu valorile de la primul vector adăugate în fața celor de la al doilea.
Metoda concat() poate fi folosită pentru a concatena mai mult de doi
vectori într-unul singur. Vectorii care vor fi concatenați vor fi între
paranteze delimitați prin virgule.

Pentru a găsi indexul unui element dintr-un vector se folosește


.indexOf(element). indexOf() este ca folosirea inversă a folosirii
parantezelor pătrate pentru a obține o valoare a unui anumit index. Dacă
un element nu este într-un vector, JavaScript va returna -1. Dacă
elementul apare de mai multe ori în vector, metoda indexOf() va returna
doar indexul primului element întâlnit în acel vector.

Folosirea metodei .join() pe un vector, pentru a uni toate elementele


acestuia, returnează un șir ce conține toate elementele vectorului
separate de virgule (virgula este separator implicit).
Programare Web - Curs 3

Dacă nu se dorește separarea elementelor prin virgule se poate folosi


metoda .join(separator) în care se precizează un anumit separator. Acest
lucru este folositor atunci când avem un vector pe care dorim să-l
transformăm într-un șir. Dacă valorile din vector nu sunt de tip String,
JavaScript le va converti în șiruri înainte de a realiza join-ul.

Putem avea numere aleatorii folosind o metodă specială numită


Math.random() care returnează un număr aleatoriu între 0 și 1 de fiecare
dată când este apelată (această metodă va returna întotdeauna un
număr mai mic decât 1). Dacă dorim un număr mai mare, putem înmulți
rezultatul returnat.

Metoda Math.floor() necesită un număr pe care îl rotunjește în jos.

Pentru a selecta un element aleatoriu dintr-un vector putem folosi un


index aleatoriu obținut prin combinarea celor două metode.

Obiectele în JavaScript sunt foarte similare cu vectorii, ele folosesc șiruri


în loc de numere pentru a accesa diferite elemente. Șirurile se numesc
chei sau proprietăți, iar elementele la care fac referire se numesc valori.
Împreună, acestea se numesc perechi cheie – valoare. În timp ce vectorii
sunt des folosiți pentru a reprezenta liste de lucruri multiple, obiectele
sunt adesea folosite pentru a reprezenta lucruri cu multiple caracteristici
sau atribute.
Programare Web - Curs 3

Pentru a crea un obiect se folosesc acoladele, în interiorul cărora se


introduc perechile cheie – valoare. Tot ceea ce se află în interiorul
obiectului, inclusiv acoladele se numesc literali de tip object.

Observație: Ne reamintim că am folosit literali numere (exemplu: 37),


literali șiruri (exemplu: “rosu”), literali booleeni (true și false), literali
vector (exemplu: [“Alozaur”, ”Pteradonon” ]). Literal înseamnă că
întreaga valoare este scrisă deodată, nu construită în pași.

De exemplu, dacă dorim să creăm un vector cu numerele 1, 2, 3 în el,


putem folosi literalul vector [1, 2, 3], sau putem crea un vector gol și apoi
folosi metoda push() pentru a adăuga 1, 2, și 3 la vector.

Sintaxa de bază pentru a crea un obiect este:

{ “key1” : 99}

în care key1 reprezintă cheia, care va fi mereu un șir (nu este obligatorie
folosirea de ghilimele pentru chei), iar 99 reprezintă valoarea pentru
cheie, valoare care poate fi de orice tip( chiar o variabilă ce conține o
valoare). Atunci când creăm un obiect, cheia este mereu în fața semnului
(:), iar valoarea după. Semnul (:) se comportă ca un egal, adică valorile
din dreapta lui sunt atribuite numelor din stânga, asemănător modului
în care creăm variabile. Între fiecare pereche cheie – valoare, trebuie pus
virgulă (exceptând ultima pereche, după care se închide acolada).
Programare Web - Curs 3

Accesul la valorile unui obiect se face folosind parantezele pătrate, la fel


ca la vectori, singura diferență fiind că în loc de index (un număr) folosim
cheia (un șir).

Pentru a obține toate cheile unui obiect, folosim


Object.keys(anyObject), care returnează un vector ce conține toate
cheile obiectului anyObject dintre parantezele rotunde.

Vectorii au o anumită ordine, index 0 este înaintea lui index 1, iar index
3 este după index 2; dar, la obiecte nu există un mod de a ordona fiecare
item. Obiectele stochează cheile fără a le atribui vreo ordine, astfel
diferite browsere (Chrome, Explorer, Opera, Mozilla) vor afișa cheile într-
o ordine diferită.

Structuri de control

a. Structura de control condițională

O declarație if(condition) este cea mai simplă structură de control


din JavaScript, pentru că este folosită pentru a rula cod doar dacă
condition este adevărată.
Programare Web - Curs 3

Dacă dorim să se întâmple altceva atunci când condition din if este


falsă, se va folosi o declarație de tip if … else.

Adesea avem nevoie să verificăm o serie de condiții și să se realizeze ceva


atunci când una dintre ele este adevărată.
Programare Web - Curs 3

b. Structura de control repetitivă

Structura de control repetitivă permite ca un cod să fie rulat de mai multe


ori, depinzând de o condiție care rămâne adevărată, iar ieșirea din buclă
va avea loc atunci când condiția devine falsă.

Cea mai simplă formă de structură de control repetitivă este dată de


while(condition). La fel ca la if , corpul buclei while este
executat dacă condition dintre paranteze este adevărată. Totuși,
spre deosebire de if, după ce este executat corpul, condition este
verificată din nou și dacă încă este adevărată va rula corpul buclei while
din nou. Acest ciclu va merge până când condition este falsă.
Programare Web - Curs 3

Dacă condiția setată în bucla while nu devine niciodată falsă, atunci


bucla va rula la infinit.

Cu ajutorul buclei for se creează o variabilă, se parcurge un ciclu până


când o condiție este adevărată și se updatează valoarea variabilei la
fiecare repetiție a corpului buclei.

Setup-ul este rulat înainte de ciclu. În general, este folosit pentru a crea
o variabilă, folosită pentru a ști numărul de execuții ale ciclului.

Condiția este verificată înainte de fiecare pornire a ciclului. Dacă aceasta


este adevărată este executat corpul buclei for, dacă nu bucla se închide.
Programare Web - Curs 3

Incrementarea este realizată după fiecare execuție a corpului buclei for,


fiind folosită pentru update-ul variabilei.

Ciclurile for sunt adesea utilizate să realizeze ceva de un anumit număr


setat de ori. Ciclul for este uzual folosit la vectori sau șiruri.
Programare Web - Curs 3

Programarea orientată-obiect în JavaScript


1. Tipuri primitive și tipuri de referință
Majoritatea dezvoltatorilor asociază programarea orientată-obiect cu limbajele studiate și de voi
până acum, C++ și Java, în care baza programării orientate-obiect este dată de clase. Înainte de a face
orice în aceste limbaje, trebuie să creezi o clasă, chiar dacă pentru a scrie o simplă linie, un simplu mesaj.
JavaScript nu folosește clase (JavaScript nu are suport formal pentru clase) și din cauza aceasta lumea
devine confuză atunci când învață acest limbaj după C++ sau Java. Limbajele orientate-obiect au câteva
caracteristici: încapsularea (datele pot fi grupate împreună cu funcționalități care operează pe acele date.
Aceasta poate fi definiția unui obiect), agregarea (un obiect poate referi alt obiect), moștenirea (un obiect
nou creat are aceleași caracteristici cu un alt obiect fără duplicare explicită a funcționalității),
polimorfismul (o interfață poate fi implementată de mai multe obiecte).

JavaScript are toate aceste caracteristici și cu toate că limbajul nu are conceptul de clasă, unele
dintre ele nu sunt implementate chiar în maniera în care v-ați aștepta să fie. La o primă vedere, un program
JavaScript poate arăta chiar ca un program procedural pe care-l scriem în C. Dacă scriem o funcție și îi
atribuim niște variabile, avem un script funcțional care aparent nu conține obiecte. La o privire mai atentă
asupra limbajului, observăm existența obiectelor, dată de folosirea (.) punctului (dot notation).

Multe limbaje orientate-obiect folosesc dot notation pentru a accesa proprietățile și metodele
obiectelor, iar JavaScript este la fel din punct de vedere sintactic. Dar, în JavaScript nu trebuie să definești
o clasă, să imporți un pachet (o grupare de clase) sau să incluzi un fișier de tipul header. Doar scrii cod cu
tipurile de date pe care le dorești și le poți grupa pe acestea în oricâte moduri. Această libertate permite
ca JavaScript să fie foarte flexibil. Pentru a ușura tranziția de la limbajele tradiționale orientate-obiect, în
JavaScript obiectele sunt partea centrală a limbajului. Aproape toate datele din JavaScript sunt fie un
obiect sau sunt accesate prin obiecte. De fapt, chiar funcțiile sunt reprezentate prin obiecte (first class
functions).

1.1. Ce sunt tipurile?


Lucrul cu obiecte și înțelegerea lor reprezintă cheia înțelegerii limbajului. Se pot crea obiecte,
adăuga sau șterge proprietăți pentru ele. Chiar dacă JavaScript nu are conceptul de clase, utilizează două
feluri de tipuri de date: tipurile primitive și tipurile de referință. Tipurile primitive sunt stocate ca tipuri
simple de date. Tipurile de referință sunt stocate ca obiecte, adică chiar o referință către locațiile din
memorie. Lucrul complicat este că JavaScript permite ca tipurile de date primitive să fie tratate ca cele de
referință pentru a face limbajul mai consistent pentru dezvoltator. În timp ce alte limbaje fac distincție
între tipurile de date primitive și cele de referință stocând pe cele primitive pe o stivă și pe cele de referință
la grămadă, în JavaScript se urmăresc variabilele pentru un anumit scop cu o variabilă obiect. Valorile
primitive sunt stocate direct pe variabila obiect, în timp ce valorile referință sunt plasate ca un pointer
către variabila obiect, ceea ce servește ca referință către locația din memorie unde este stocat obiectul.
Programare Web - Curs 3

1.2. Tipurile primitive


Reprezintă simple piese de date care sunt stocate ca atare. Există 5 tipuri de tipuri primitive în JavaScript:
Boolean, Number, String, Null, Undefined (are o singură valoare undefined, valoare atribuită unei
variabile care nu este inițializată). Toate tipurile primitive au o reprezentare literală a valorilor. În
JavaScript, o variabilă care ține o primitivă conține direct valoarea primitivei, mai degrabă decât un pointer
la un obiect. Atunci când este alocată o valoare primitivă unei variabile, acea valoare este copiată în
variabilă, acest lucru înseamnă că atunci când setați o variabilă egală cu o alta, fiecare din cele două
variabile va avea propria copie a datelor. Din cauză că fiecare din cele două variabile ce conțin o valoare
primitivă folosește propriul spațiu de stocare, schimbările pentru una din variabile nu se reflectă și asupra
celeilalte.

Cea mai bună modalitate de a identifica tipurile primitive este dată de folosirea operatorului typeof,
care aplicat asupra oricărei variabile returnează un șir ce indică tipul de dată. Așa cum ne amintim,
typeof returnează string atunci când valoarea este un șir, number atunci când valoarea este un
număr, boolean atunci când valoarea este un boolean și undefined atunci când valoarea este
undefined. Partea interesantă este atunci când valoarea este null. Atunci când se aplică operatorul
typeof lui null rezultatul este object. Un raționament posibil pornește de la faptul că null este
privit ca un obiect pointer gol ceea ce înseamnă că valoarea logică întoarsă să fie object.

În ciuda faptului că sunt tipuri de date primitive String, Number și Boolean au metode (null și
undefined nu au metode). De exemplu, șirurile, în particular, au numeroase metode: lowerCase(),
toString(), charAt(), substring(), slice()…

În ciuda faptului că au metode, valorile primitive nu sunt obiecte!


1.3. Tipurile referință
Reprezintă obiecte în JavaScript. Valorile referință sunt instanțe ale tipurilor referință și sunt sinonime cu
obiectele. Un obiect este o listă neordonată de proprietăți care conțin un nume (întotdeauna un șir) și o
valoare. Atunci când valoarea unei proprietăți este o funcție, aceasta este numită metodă. Funcțiile sunt
ele însele valori referință în JavaScript, deci va fi o mică diferență între o proprietate care conține un vector
și una care conține o funcție.

Există mai multe moduri de a crea sau instanția obiecte. Primul mod este dat de folosirea operatorului
new cu un constructor( un constructor reprezintă o simplă funcție ce folosește new pentru a crea un
obiect – orice funcție poate fi un constructor) Prin convenție, constructorii în JavaScript încep cu o
majusculă, pentru a face distincție față de funcțiile care nu sunt constructori. De exemplu, în următorul
cod se instanțiază un obiect generic și se stochează o referință către acesta în object:

Tipurile referință nu stochează obiectul direct în variabila care-i este atribuită, deci variabila object din
exemplul de mai sus nu conține în mod real instanța obiectului, ci un pointer (sau o referință) către locația
din memorie unde există obiectul. Aceasta este diferența principală între obiecte și valori primitive,
deoarece primitiva este stocată direct în variabilă.
Programare Web - Curs 3

Atunci când atribui un obiect unei variabile, de fapt se atribuie un pointer. Acest lucru înseamnă că dacă
atribui o variabilă unei alte variabile, fiecare din acestea primește o copie a pointerului, ambele făcând
referință către același obiect în memorie:

În acest cod, mai întâi se creează un obiect (folosind new) și se stochează referința în object1. Apoi, lui
object2 îi este atribuită valoarea lui object1. Cu toate că este o singură instanță a obiectului care a
fost creat la prima linie, ambele variabile au referință către același obiect:

În JavaScript atunci când nu mai sunt referințe către un obiect din memorie, garbage collector poate folosi
acea memorie pentru altceva. Acest lucru se realizează prin setarea unui obiect la null:

Un alt aspect interesant al obiectelor în JavaScript este dat de faptul că se pot adăuga sau înlătura
proprietăți la orice moment de timp:

Aici, myCustomProperty este adăugată lui object1 cu valoarea SIMPLU. Această proprietate este
accesibilă și lui object2 deoarece ambele variabile au referință către același obiect.

1.4. Tipurile referință ce pot fi instanțiate folosind new, la orice moment de timp
sunt: Array (o listă ordonată de valori numerice indexate), Date (data și ora), Error(o eroare
de execuție, există mai multe subtipuri specifice de erori), Function(o funcție), Object( un
obiect generic), RegExp(o expresie regulată). Câteva dintre tipurile referință de mai sus au forme
literale. Un literal este o sintaxă care permite definirea unei valori referință fără a crea în mod
explicit un obiect, folosind operatorul new și constructorul obiectului.

Pentru a crea un obiect literal se pot defini proprietățile noului obiect între acolade. Proprietățile sunt
formate dintr-un identificator sau un șir, (:) și o valoare cu mai multe proprietăți separate prin virgule:
Programare Web - Curs 3

În cele două exemple anterioare echivalente avem un obiect cu două proprietăți (name, year).

Se poate defini un vector literal într-un mod similar:

JavaScript folosește literali expresii regulate, ceea ce permite definirea de expresii regulate fără folosirea
constructorului RegExp. Literalii expresii regulate arată ca expresiile regulate din limbajul Perl: modelul
este conținut între două slash-uri și orice alte opțiuni suplimentare sunt date de un caracter singular ce
urmează după al doilea slash:

Forma literală a unei expresii regulate în JavaScript este de preferat formei ce folosește constructorul, cu
excepția cazului în care expresia regulată este construită dinamic din unul sau mai multe șiruri.

1.5. Accesul la proprietăți


Proprietățile reprezintă perechi nume – valoare ce sunt stocate într-un obiect. Cea mai comună metodă
de acces la proprietăți în JavaScript (de altfel și la alte limbaje orientate-obiect) este dată de folosirea
punctului (dot notation). O altă modalitate de a accesa proprietățile obiectelor în JavaScript este folosirea
de paranteze pătrate (bracket notation) cu un șir. Această sintaxă este folositoare atunci când decizi
dinamic ce proprietate să accesezi. De exemplu, al treilea cod permite o variabilă în locul unui literal șir
pentru a specifica proprietatea de acces:

Dot notation: Bracket notation: Bracket notation:

Variabila method are valoare push, deci push() este apelată pe vector. Singura diferență în afară de sintaxă
între cele două moduri de acces la proprietăți este dată de faptul că la bracket notation se permite
folosirea de caractere speciale în numele proprietății.

1.6. Identificarea tipurilor referință


Folosirea unei funcții este cea mai ușoară cale de a identifica tipurile referință, de exemplu, atunci când
folosim operatorul typeof pe o funcție, operatorul ar trebui să returneze function:
Programare Web - Curs 3

Alte tipuri referință sunt mai greu de identificat, deoarece pentru toate celelalte tipuri referință cu
excepția funcțiilor, typeof returnează object. Pentru a identifica tipurile referință mai ușor, se poate
folosi operatorul instanceof. Operatorul are ca parametri un obiect și un constructor. Atunci când
valoarea este o instanță a tipului specificat de constructor, instanceof returnează true, altfel,
returnează false:

Pe lângă folosirea operatorului instanceof, pentru a identifica vectori se poate folosi metoda
Array.isArray() ce identifică valoarea (ce poate fi trecută între cadre în aceeași pagină web) ca
instanță a lui Array, referitor la valoarea originală. Această metodă ar trebui să întoarcă true atunci când
primește o valoare care este un vector în orice context:

2. Funcții
Definirea unei funcții seamănă cu definirea unei variabile, numai că valoarea pe care o primește variabila
este o funcție. De exemplu, următorul cod definește o variabilă numită patrat() care se referă la o
funcție ce întoarce pătratul unui număr dat:

O funcție este creată de o expresie care începe cu un cuvânt cheie function. Funcțiile au un set de
parametri (în acest caz, doar unul singur, x) și un corp, care conține afirmații ce vor fi executate atunci
când este apelată funcția. Corpul funcției va fi mereu între acolade, chiar dacă conține o singură
instrucțiune, ca în exemplu.

O funcție poate să nu aibă nici un parametru:


Programare Web - Curs 3

O funcţie poate avea mai mulți parametri:

Unele funcții returnează o valoare, așa cum e putere() și patrat(), unele nu (zgomot()). Return
determină valoarea întoarsă de o funcție. Dacă nu urmează nici o expresie după return, atunci funcția
va întoarce undefined.

Parametrii unei funcții se comportă ca variabile oarecare, cu valorile inițiale date la apelul funcției. O
proprietate importantă a funcțiilor este aceea că variabilele create în interiorul acesteia, inclusiv
parametrii acestora se numesc variabile locale ( exemplu, variabila rezultat din funcția putere() va
fi creată de fiecare dată la apelul funcției).

Variabilele declarate în afara funcției se numesc variabile globale, deoarece sunt vizibile oriunde în
interiorul programului. Accesul acestora este posibil din interiorul unei funcții atâta timp cât nu s-au
declarat variabile locale cu același nume.

Exemplu:

Funcțiile pot fi create în interiorul altor funcții. Valoarea unei funcții poate fi folosită în expresii arbitrare,
sau poate fi stocată într-o altă valoare, poate fi folosită ca argument al altei funcții…În mod similar, o
variabilă care conține o funcție se comportă ca o variabilă oarecare, căreia i se poate atribui o nouă
valoare.
Programare Web - Curs 3

Cuvântul cheie function poate fi folosit ca și începutul unei afirmații, ca de exemplu în declarația
următoare:

Aceasta este declarația unei funcții. Afirmația definește variabila patrat către funcția data.

În exemplul următor, funcția este definită după codul care o apelează:

Exemplul următor tratează clasica problemă a oului și găinii… Cine este primul?

La execuția codului anterior, veți observa un mesaj de eroare, de forma: ”Maximum call stack size
exceeded”. Acest mesaj apare deoarece o funcție trebuie să sară înapoi la locul unde era atunci când a
fost apelată și returnează ceva. Locul în care computerul stochează contextul acesta se numește stiva de
apeluri. De fiecare dată când o funcție este apelată, contextul curent este pus în vârful stivei. Atunci când
funcția returnează, se elimină contextul din vârful stivei. Stocarea acestei stive necesită spațiu în memoria
computerului. Atunci când stiva crește prea mult, computerul va da un mesaj de forma: ”out of stack
space” sau “too much recursion”.

Codul anterior întreabă computerul o întrebare cu adevărat grea, care cauzează o buclă infinită între cele
două funcții gaina() și ou(). Bucla ar fi infinită dacă computerul ar avea o stivă infinită.

Următorul cod este permis și se execută fără nici o problemă:

Funcția alert nu acceptă decât un singur argument. Totuși, atunci când este apelată, așa cum apare mai
sus, se va ignora celălalt argument și va afișa doar pe primul, adică “Salut”. În JavaScript numărul de
argumente ale unei funcții pot fi tratate destul de ciudat, poate veți spune: dacă sunt prea multe, cele
extra sunt ignorate, dacă sunt prea puține, celor care lipsesc li se atribuie valoarea undefined. Partea
bună a acestui comportament este că poți defini, de exemplu, o funcție care să aibă argumente opționale.
Programare Web - Curs 3

De exemplu, următorul cod, prezintă o versiune a funcției putere() care poate avea fie două
argumente, fie doar unul, în acest caz exponentul va fi 2, iar funcția se va comporta ca funcția patrat():

Abilitatea de a trata funcțiile ca și valori, combinată cu faptul că variabilele locale sunt recreate de fiecare
dată la apelul unei funcții, ridică o întrebare interesantă: Ce se întâmplă cu variabilele locale atunci când
funcția care le-a creat nu mai este activă?

O funcție care se apelează pe ea însăși se numește funcție recursivă.

De exemplu:

Funcția se apelează pe ea însăși de mai multe ori cu diferite argumente pentru a ajunge la înmulțirea
repetată. Această implementare este de aproximativ 10 ori mai înceată decât o buclă, deoarece rularea
unei bucle este mai rapidă decât apelul de mai multe ori a unei funcții. Dilema între viteză și eleganță este
interesantă.

Cazul anterior al variantei prezentate pentru funcția putere () (cu bucla for, cea cu argumentele opționale),
este o versiune mai simplă și ușor de citit, dar totuși neelegantă. Regula de bază este să nu vă îngrijorați
asupra eficienței până nu știți cu siguranță că programul este prea încet.

Recursivitatea nu este întotdeauna doar o alternativă mai puțin eficientă a unui ciclu. Unele probleme
sunt mai ușor de rezolvat cu recursivitate decât cu bucle while sau for.
Programare Web - Curs 3

De exemplu:

Cum scrieți o funcție recursivă, care rezolvă: fiind dat numărul 1 și repetând fie adunarea cu 5 sau
înmulțirea cu 3, să obțineți alte numere. Adică,

1=1

6 = 1+5

8 = (1*3) + 5

11 =(1 + 5) + 5

13 = ((1 *3) +5 ) +5

16 = (1 + 5 ) +5 + 5

18 = (1 + 5) *3

24 = ((1*3) +5) *3

33 = ((1 +5) + 5) *3

function gasesteSolutia(x) {
function gaseste(a, b){
if (a == x)
return b;
else if (a > x)
return null;
else
return gaseste(a + 5, "(" + b + "
+5)") || gaseste(a * 3, "(" +b + " *3)");
}
return gaseste (1, "1");
}

console.log(gasesteSolutia(24));//(((1*3) +5) *3)


Programare Web - Curs 3

Funcțiile sunt obiecte în JavaScript. Caracteristica definitorie a unei funcții (prin care se deosebește de un
obiect) este prezența unei proprietăți interne numite [[Call]]. Proprietățile interne nu sunt accesibile
prin intermediul codului, mai degrabă definesc comportamentul codului (conțin instrucțiunile de execuție)
în timp ce acesta se execută. ECMAScript definește multiple proprietăți interne pentru obiecte în
JavaScript, iar acestea sunt indicate prin duble paranteze pătrate. Proprietatea [[Call]] este unică
funcțiilor și indică faptul că obiectul poate fi executat. Deoarece doar funcțiile au această proprietate,
operatorul typeof este definit de ECMAScript să returneze function pentru orice obiect cu
proprietatea [[Call], (adică operatorul typeof caută după această proprietate internă și dacă o
găsește returnează function). Numărul de argumente pe care îl așteaptă o funcție este dat de folosirea
proprietății length:

Creăm o funcție care acceptă un număr nelimitat de parametri și care returnează suma acestora:

Funcția suma() acceptă orice număr de parametri și îi adună, iar dacă nu i se dă nici un parametru
returnează 0 pentru că variabila rezultat a fost inițializată cu valoarea 0.

Atunci când o proprietate este chiar o funcție, proprietatea este considerată o metodă. De exemplu, în
următorul cod, variabilei persoana îi este atribuit un obiect literal cu o proprietate nume și o metodă
numită spuneNume:
Programare Web - Curs 3

Al doilea cod se comportă asemănător cu primul, numai că metoda spuneNume() se referă la this în
loc de persoana. Acest lucru înseamnă că se poate schimba numele variabilei sau se poate reutiliza
funcția pe obiecte diferite. Variabila globală nume are valoarea Popa, iar atunci când este apelată
spuneNumeleTuturor(), aceasta va afișa Popa pentru că variabila globală este considerată o
proprietate a obiectului global.

Prima formă de manipulare a lui this este dată de folosirea lui call(), ce execută funcția cu o valoare
particulară pentru this și cu parametri specifici. Primul parametru pentru call() este valoarea cu care
this ar trebui să fie egal atunci când este executată funcția. Toți parametrii ulteriori sunt parametrii care
ar trebui trecuți în funcție.

De exemplu, modificăm metoda spuneNumeleTuturor() pentru a avea un parametru ce este folosit


ca o etichetă pentru valoarea de output:

A doua formă de manipulare a lui this este dată de folosirea lui apply(), ce se execută la fel ca la
call(), cu excepția faptului că aceasta acceptă doar 2 parametri: valoarea pentru this și un vector
sau un obiect de argumente. Deci, în loc de numirea fiecărui parametru folosind call(), se poate folosi
cu ușurință vectori la apply() pentru al doilea argument:
Programare Web - Curs 3

Metoda pe care o folosim practic depinde de tipul de dată pe care-l avem. Dacă avem deja un vector de
date, vom folosi apply(), iar dacă avem variabile individuale vom folosi call().

A treia formă de manipulare a lui this este dată de folosirea lui bind(). Această metodă a fost
adăugată în ECMAScript 5 și se comportă puțin diferit față de celelalte două. Primul argument al lui bind()
este valoarea lui this pentru noua funcție. Toate celelalte argumente reprezintă parametri ce ar trebui
să fie setați permanent în noua funcție.

S-ar putea să vă placă și