Documente Academic
Documente Profesional
Documente Cultură
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.
{ “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
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
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.
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).
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()…
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).
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.
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.
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.
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.
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ă.
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ă?
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");
}
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.
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.