Sunteți pe pagina 1din 40

Programare Web - Curs 2

Rezolvare Tema 1/Laborator 1:

Să se creeze un program JavaScript care să transforme șirul

“bUNă ZIUA, cE MAI fAceȚI?” în “Bună ziua, ce mai faceți?”

Rezolvare Tema2/Laborator1:

a. Cum verificați dacă o variabilă a fost sau nu definită în sistem?

b. Cum verificați dacă o variabilă a fost definită, este un șir și nu este

gol?

Rezolvare Tema3/Laborator1:

Înlocuiți în lista de cumpărături, cirese cu caise și mere cu pere și afișați


noua listă. Pentru aceasta studiați metoda replace().

Page 1 of 40
Programare Web - Curs 2

Rezolvare Tema1/Laborator2:

Să se caute în vectorul Dinozauri după valorile Alozaur și Apatozaur și să


se obțină indexul elementului dacă este găsit.

Page 2 of 40
Programare Web - Curs 2

Rezolvare Tema2/Laborator2:

Exercițiu STIVA(LIFO): Realizați un traseu de parcurgere a distanței de


acasă până la facultate, care să conțină o listă cu minim 8 puncte
principale (landmarks) pe care le vedeți pe drum. Pe drumul de
întoarcere către casă, lista va trebui parcursă în ordinea inversă și
verificat fiecare item de la finalul listei inițiale, de fiecare dată când
vedeți unul din punctele principale pentru a ști unde trebuie mers în
continuare (drumul este imaginat: casă – facultate – casă).

Primul landmark va fi ultimul scos din listă, iar ultimul punct principal
(landmark) va trebui să fie primul scos din listă…

Page 3 of 40
Programare Web - Curs 2

Page 4 of 40
Programare Web - Curs 2

Rezolvare problema propusă la Curs 1:

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

Page 5 of 40
Programare Web - Curs 2

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
Page 6 of 40
Programare Web - Curs 2

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.

Page 7 of 40
Programare Web - Curs 2

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).

Page 8 of 40
Programare Web - Curs 2

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.

Page 9 of 40
Programare Web - Curs 2

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).

Page 10 of 40
Programare Web - Curs 2

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

Page 11 of 40
Programare Web - Curs 2

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

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.

Page 12 of 40
Programare Web - Curs 2

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

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

Page 13 of 40
Programare Web - Curs 2

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

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.

Page 14 of 40
Programare Web - Curs 2

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.

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.

Page 15 of 40
Programare Web - Curs 2

Programarea orientată-obiect în JavaScript

1. Tipuri primitive și tipuri 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ă
Page 16 of 40
Programare Web - Curs 2

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 referință. Tipurile primitive
sunt stocate ca tipuri simple de date. Tipurile 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

Page 17 of 40
Programare Web - Curs 2

tratate ca cele referință pentru a face limbajul mai consistent pentru


dezvoltator. În timp ce alte limbaje fac distincție între tipurile de date
primitive și cele referință stocând pe cele primitive pe o stivă și pe cele
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.

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 (nu un pointer la 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.

Page 18 of 40
Programare Web - Curs 2

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

Page 19 of 40
Programare Web - Curs 2

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

Atunci când atribui un obiect unei variabile, de fapt se atribuie un


pointer. Acest lucru înseamnă că dacă atribui o variabilă unei alte

Page 20 of 40
Programare Web - Curs 2

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:

Page 21 of 40
Programare Web - Curs 2

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:
Page 22 of 40
Programare Web - Curs 2

Î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:

Page 23 of 40
Programare Web - Curs 2

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:

Page 24 of 40
Programare Web - Curs 2

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:

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:

Page 25 of 40
Programare Web - Curs 2

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:

Page 26 of 40
Programare Web - Curs 2

2. Funcții

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:

Page 27 of 40
Programare Web - Curs 2

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:

Page 28 of 40
Programare Web - Curs 2

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:
Page 29 of 40
Programare Web - Curs 2

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:

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().

Page 30 of 40
Programare Web - Curs 2

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.

Page 31 of 40
Programare Web - Curs 2

3. Obiecte în JavaScript

Obiectele în JavaScript sunt dinamice, se pot schimba în orice moment al


execuției codului. Ne amintim că există două moduri de a crea un obiect:
folosind constructorul Object sau folosind un literal obiect:

Ambele persoana1 și persoana2 sunt obiecte cu proprietatea


nume. Apoi, ambele obiecte au atribuită proprietatea varsta. Se
poate face acest lucru imediat după definirea obiectului sau mai târziu.
Obiectele create se pot modifica constant (cu excepția faptului când este
specificat contrariul!). Apoi, se schimbă valoarea lui nume pentru fiecare
obiect, valorile proprietății pot fi schimbate oricând. Atunci când este
adăugată o proprietate la un obiect, JavaScript folosește o metodă
internă numită [[Put]] asupra obiectului. Metoda [[Put]] creează
un loc în obiect pentru a stoca proprietatea. Rezultatul apelului metodei
[[Put]] este crearea unei proprietăți proprii obiectului. Proprietatea

Page 32 of 40
Programare Web - Curs 2

este stocată direct în instanță și toate operațiile pe acea proprietate


trebuie realizate prin obiect.

Proprietățile proprii sunt diferite de proprietățile prototype!!

Atunci când este atribuită o nouă valoare unei proprietăți existente are
loc o operație separată numită [[Set]] . Această operație înlocuiește
valoarea curentă a proprietății cu cea nouă. În exemplul dat, setarea
numelui cu a doua valoare rezultă la apelarea lui [[Set]] :

persoana1 persoana1
persoana1

nume Ilie nume Grigore


nume Ilie
varsta 25
[[Put]] nume varsta 25

[[Put]] varsta [[Set]]


nume

în prima parte a diagramei, un literal obiect este folosit pentru a crea


obiectul persoana1, adică se efectuează un [[Put]] implicit pentru
proprietatea nume. Atribuirea unei valori pentru persoana1.varsta duce
la un [[Put]] implicit pentru proprietatea varsta. Setarea lui
persoana1.nume cu o nouă valoare (Grigore) duce la o
operație[[Set]] pe proprietatea nume, suprascriind valoarea deja
existentă a acesteia.
Page 33 of 40
Programare Web - Curs 2

3.1. Detectarea proprietăților unui obiect

Din cauză că proprietățile pot fi adăugate în orice moment, uneori mai


este necesară și o căutare a unei proprietăți într-un obiect. Acest lucru
nu se face cu if, așa cum poate ați gândit , ci cu operatorul in, care
caută după o proprietate cu un nume dat într-un obiect specific și
returnează true dacă o găsește:

Reamintesc că metodele sunt doar proprietăți care fac referință la


funcții, deci se poate căuta existența unei metode în același mod. În
următorul cod adaug o funcție, spuneNume() la persoana1 și
folosesc operatorul in pentru a confirma prezența funcției în obiect:

În majoritatea cazurilor, operatorul in este cea mai bună modalitate de


a determina dacă o proprietate există într-un obiect, deoarece are
beneficiul de a nu evalua valoarea proprietății. În unele cazuri se poate

Page 34 of 40
Programare Web - Curs 2

căuta existența unei proprietăți a unui obiect, doar dacă aceasta este o
proprietate proprie acelui obiect. Operatorul in caută și după
proprietăți proprii și după proprietăți prototype, deci ne trebuie o altă
abordare.

Metoda hasOwnProperty() este prezentă la toate obiectele și returnează


true doar dacă proprietatea dată există și este o proprietate proprie
obiectului. De exemplu, în următorul cod se compară rezultatul folosirii
operatorului in și a metodei hasOwnProperty() pe diferite
proprietăți ale obiectului persoana1:

În exemplul dat, nume este o proprietate proprie obiectului


persoana1, deci ambele metode (atât folosirea operatorului in cât și
folosirea metodei hasOwnProperty()) întorc true.

Metoda toString() este o proprietate prototype care este prezentă


la toate obiectele. Operatorul in întoarce true pentru toString(),
dar hasOwnProperty() întoarce false.

Page 35 of 40
Programare Web - Curs 2

3.2. Înlăturarea proprietăților unui obiect

Așa cum proprietățile pot fi adăugate obiectelor la orice moment de


timp, ele pot fi și înlăturate. Setarea unei proprietăți la null nu o
înlătură complet din obiect! O astfel de operație numită [[Set]] cu o
valoare de null, așa cum am văzut în diagramele de mai sus, doar
înlocuiește valoarea proprietății. Pentru a înlătura total o proprietate
dintr-un obiect trebuie folosit operatorul delete. Acesta acționează
asupra unui singur obiect și apelează o operație internă numită
[[Delete]]. Atunci când operatorul delete acționează va întoarce
true (unele proprietăți nu pot fi înlăturate):

În exemplu este ștearsă proprietatea nume din obiectul persoana1.


Operatorul in returnează false după ce operația este completă. De
asemenea, observați că accesul la o proprietate care nu există va
întoarce undefined.

Page 36 of 40
Programare Web - Curs 2

3.3. Enumerarea

Implicit, toate proprietățile pe care le adăugăm unui obiect sunt


numărabile, adică se pot folosi în bucle for -in. Proprietățile
numărabile au propriile atribute interne [[Enumerable]] setate la
true. O buclă for-in enumeră toate proprietățile numărabile ale unui
obiect, atribuind numele proprietății unei variabile. De exemplu,
următoarea buclă produce numele proprietăților și valorile unui obiect:

De fiecare dată când se parcurge bucla for-in , variabilei property


îi este atribuită următoarea proprietate numărabilă a obiectului, până
când toate proprietățile au fost folosite. La acel moment de timp, bucla
este terminată și se continuă execuția codului. În acest exemplu este
folosită bracket notation pentru a obține valoarea proprietății
obiectului și a o afișa în consolă. Dacă avem nevoie de o listă de
proprietăți ale obiectului pe care să o folosim ulterior, se folosește
metoda Object.keys() pentru a obține un vector de nume de
proprietăți numărabile ale obiectului object:

Page 37 of 40
Programare Web - Curs 2

Există o diferență între proprietățile numărabile returnate de o buclă for-


in și cele returnate de Object.keys(). Bucla for-in enumeră și proprietățile
prototype, în timp ce Object.keys() returnează doar proprietăți proprii.
Nu toate proprietățile sunt numărabile. Majoritatea metodelor proprii
obiectelor au atributele [[Enumerable]] setate la false. Dacă o
proprietate a unui obiect este sau nu numărabilă se verifică cu ajutorul
metodei propertyIsEnumerable():

Proprietatea nume este numărabilă, fiind o proprietate proprie definită


pe obiectul persoana1. Proprietatea length din vectorul
properties nu este numărabilă deoarece este o proprietate de tip
built-in pe Array.prototype.

Page 38 of 40
Programare Web - Curs 2

3.4. Tipuri de proprietăți

Există două tipuri diferite de proprietăți: proprietăți de date ce conțin o


valoare precum proprietatea nume din exemplul anterior
(comportamentul metodei [[Put]] este de a crea o proprietate de
date) și proprietăți accesor ce nu conțin o valoare, ci definesc o funcție
pentru a o apela atunci când proprietatea este citită (getter) și o funcție
pentru a o apela atunci când proprietatea este scrisă (setter).

Sintaxa pentru a defini o proprietate accesor folosind un literal obiect:

Sintaxa folosită pentru definirea lui getter și setter pentru name


arată la fel ca la funcții, dar fără a se folosi cuvântul cheie function.
Cuvintele speciale get și set sunt folosite în fața numelui proprietății
accesor, urmate de paranteze și un corp de funcție. Getter se

Page 39 of 40
Programare Web - Curs 2

așteaptă să întoarcă o valoare, în timp ce setter primește acea valoare


ca fiind atribuită proprietății ca un argument.

Page 40 of 40

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