Pass by Value vs Pass By Reference în JavaScript

dacă sunteți nou în JavaScript, este posibil să vă confruntați deja cu unele dintre comportamentele amuzante pe care le oferă această limbă (expoziția A). La început, aceste ciudățenii ciudate ar putea părea ridicole și frustrante, dar promit că există o metodă în spatele acestei nebunii.

unul dintre cele mai grele obstacole de depășit, în umila mea părere, este diferența dintre trecerea prin valoare și trecerea prin referință. De ce este acest concept atât de complicat? Pentru început, cu siguranță puteți ajunge destul de departe fără a înțelege cu adevărat modul în care JavaScript interacționează cu valorile primitive și valorile de referință. Acest lucru poate, și cel mai adesea, va duce la o tona de bug-uri, care sunt greu pentru a urmări în jos și enervant pentru a repara. În al doilea rând, acesta este un concept care va apărea în interviurile tehnice, astfel încât neînțelegerea acestuia va conta ca un steag roșu imens împotriva ta.

nu te teme, prietene cititor! Să înceapă educația …

tipuri de date Primitive

în JavaScript, putem împărți tipurile de date în două găleți diferite, tipuri de date primitive și obiecte.

diagramă care ilustrează tipurile de date primitive sau valorile și tipurile de obiecte sau valorile de referință

există șase tipuri de date primitive în JavaScript: string, number, boolean, undefined, null, și symbol ca de ES6.

tipurile de date Primitive sunt transmise sau copiate după valoare și sunt imuabile, ceea ce înseamnă că valoarea existentă nu poate fi modificată așa cum o matrice sau un obiect poate. Să aruncăm o privire la codul de mai jos pentru a vedea acest lucru în acțiune.

creat folosind jsbin.com

aici am creat două variabile, x = 10și y = x. Deoarece 10 este un număr și o valoare primitivă, atunci când setăm y = x copiem de fapt valoarea, adică 10și o atribuim y. De asemenea, putem vizualiza acest lucru folosind graficul de mai jos.

dacă ar fi să schimbăm valoarea x, am vedea că yîși păstrează valoarea 10. Din nou, acest lucru se datorează faptului că valorile primitive sunt copiate, deci valoarea yeste independentă de valoarea x. Gândiți-vă la asta ca la o fotocopie a unei imagini. După efectuarea copiei, aveți două imagini identice: un original și un facsimil. Dacă ar fi să tăiați originalul în jumătate, numai originalul ar fi modificat și facsimilul ar rămâne exact același.

am suprascris valoarea lui x, dar y rămâne aceeași

obiecte de referință

obiectele, pe de altă parte, sunt transmise prin referință și indică o locație din memorie pentru valoare, nu valoarea în sine. Să aruncăm o privire la acest lucru în codul nostru.

variabilele x și y indică acum obiecte mai degrabă decât tipuri de date primitive

în acest exemplu, x este acum un obiect care indică {dog: "poodle"}. Când creăm variabila y și îi atribuim valoarea x, acum putem accesa diferitele proprietăți ale x care include valoarea pentru dog, adică "poodle". Aceasta pare a fi exact aceeași logică folosită pentru valorile primitive, dar să aruncăm o privire la graficul nostru la îndemână de mai jos pentru a vedea diferența subtilă, dar importantă.

atât X, cât și Y indică o adresă (alcătuită) din memorie care stochează o referință la obiectul

acum, această diagramă arată puțin diferită de atunci când variabilele noastre x și y dețineau tipuri de date primitive. În această versiune, vedem că valorile pentru ambele x și y nu sunt tipuri de date, ci referințe la o adresă din memorie, aceeași adresă de fapt! Acum să aruncăm o privire la ce se întâmplă cu x dacă adăugăm o nouă proprietate a size la y

x returnează încă un obiect, dar acum are o proprietate suplimentară de size de asemenea! Din nou, acest lucru se datorează faptului că atât x, cât și y indică același obiect de referință, astfel încât orice modificări aduse unei variabile vor fi vizibile în cealaltă.

diagrama ilustrează modul în care o schimbare în y actualizează valoarea de referință care este partajată cu x

pentru a mă ajuta să-mi amintesc acest concept, îmi place să mă gândesc la valorile de referință ca la o casă și la variabile ca la oameni care locuiesc în acea casă. Toți locuitorii (variabilele) pot spune „Am o casă” și indică aceeași casă. Dacă un singur rezident decide că vrea să picteze casa în galben, atunci toți locuitorii au acum o casă galbenă, deoarece este împărțită.

să aruncăm o privire la încă un exemplu care conține o varietate de obiecte de referință.

în acest cod, începem cu o variabilă person care conține proprietăți De name, age și hobbies. Când imprimăm acest obiect pe consolă, obținem exact ceea ce ne așteptăm — același obiect pe care tocmai l-am creat.

apoi, avem o funcție numită changePerson care preia un argument, face câteva modificări, apoi returnează un obiect. Când creăm variabila thirdPerson, invocăm funcția changePerson trecând Obiectul nostru original de person în ea. Partea interesantă este ce se întâmplă când imprimăm din nou pe consola thirdPerson și person.

observați că console.log(thirdPerson) returnează un obiect cu totul nou cu proprietăți noi. Acum uita-te la ceea ce console.log(person) se întoarce. Acest lucru este similar cu obiectul nostru original, dar conține noi valori de proprietate care au fost introduse în funcția noastră changePerson.

verificarea egalității

în cele din urmă, să aruncăm o privire la modul în care tipurile de date primitive și obiectele de referință se comportă cu operatorii de egalitate.

când vine vorba de tipuri de date primitive, nu contează ce este în dreapta semnului =, atâta timp cât valorile sunt aceleași. Putem vedea acest lucru mai sus cu variabile a și b care sunt scrise diferit, dar se evaluează la aceeași valoare atunci când folosim ===, operatorul de egalitate strictă.

opusul este adevărat în al doilea exemplu pentru dogși cat. Deși poate părea că acestea conțin valori identice, este o matrice și un obiect de referință, ceea ce înseamnă că === verifică dacă ambele dog și cat au aceeași referință la valoarea din memorie. Pe de altă parte, bird === dog este adevărat deoarece împărtășesc același obiect de referință.

câinele și pasărea împărtășesc aceeași referință, în timp ce pisica nu are în ciuda faptului că are o matrice identică

concluzie

și care încheie introducerea noastră în pass by value vs pass by reference. Există mai multe subiecte care pot fi acoperite sub această umbrelă fundamental, inclusiv ce se întâmplă atunci când o referință este suprascrisă sau pierdută, cum să copiați o referință pentru a crea un obiect nou și asigurați-vă că copia este o copie profundă, doar pentru a numi câteva. Aș recomanda verificarea resurselor pe care le-am folosit mai jos, care intră în unele dintre aceste subiecte suplimentare în detaliu.

Lasă un răspuns

Adresa ta de email nu va fi publicată.