Curs 2 [PDF]

  • 0 0 0
  • Gefällt Ihnen dieses papier und der download? Sie können Ihre eigene PDF-Datei in wenigen Minuten kostenlos online veröffentlichen! Anmelden
Datei wird geladen, bitte warten...
Zitiervorschau

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 întro 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

nume

Ilie

nume

Grigore

25

varsta

25

Ilie

[[Put]] nume varsta

[[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ă forin ș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