Passa per valore vs Passa per riferimento in JavaScript

Se sei nuovo in JavaScript, è probabile che tu abbia già incontrato alcuni dei comportamenti divertenti che questo linguaggio ha da offrire (allegato A). All’inizio, queste strane stranezze potrebbero sembrare ridicole e frustranti, ma prometto che c’è un metodo dietro tutta quella follia.

Uno degli ostacoli più difficili da superare, a mio modesto parere, è la differenza tra passare per valore e passare per riferimento. Perché questo concetto è così complicato? Per cominciare, puoi sicuramente andare abbastanza lontano senza capire davvero come JavaScript interagisce con valori primitivi e valori di riferimento. Questo può, e il più delle volte, si tradurrà in una tonnellata di bug che sono difficili da rintracciare e fastidioso per risolvere. In secondo luogo, questo è un concetto che verrà fuori nelle interviste tecniche, quindi non capirlo conterà come un’enorme bandiera rossa contro di te.

Non temere, collega lettore! Lascia che l’istruzione abbia inizio

Tipi di dati primitivi

In JavaScript, possiamo dividere i tipi di dati in due diversi bucket, tipi di dati primitivi e oggetti.

il Grafico illustra i tipi di dati primitivi, o i valori, e i tipi di oggetti, o di valori di riferimento

Ci sono sei tipi di dati primitivi in JavaScript: string, number, boolean, undefined, null, e symbol come di ES6.

I tipi di dati primitivi vengono passati o copiati in base al valore e sono immutabili, il che significa che il valore esistente non può essere modificato come un array o un oggetto. Diamo un’occhiata al codice qui sotto per vedere questo in azione.

Creato utilizzando jsbin.com

Qui abbiamo creato due variabili, x = 10 e y = x. Poiché 10 è un numero e un valore primitivo, quando impostiamo y = x stiamo effettivamente copiando il valore, cioè 10, e assegnandolo a y. Possiamo anche visualizzare questo utilizzando il grafico qui sotto.

Se dovessimo cambiare il valore di x, vedremmo che ymantiene il suo valore di 10. Di nuovo, questo perché i valori primitivi vengono copiati, quindi il valore di yè indipendente dal valore di x. Pensate a come fare una fotocopia di una foto. Dopo aver effettuato la copia, hai due immagini identiche: un originale e un facsimile. Se si dovesse tagliare l’originale a metà, solo l’originale sarebbe alterato e il facsimile rimarrebbe esattamente lo stesso.

Abbiamo sovrascritto il valore di x, ma y rimane la stessa

Oggetti

Oggetti, invece, sono passati per riferimento e scegliere un percorso nella memoria per il valore, non il valore stesso. Diamo un’occhiata a questo nel nostro codice.

Le variabili x e y ora puntano a oggetti anziché a tipi di dati primitivi

In questo esempio, xè ora un oggetto che punta a {dog: "poodle"}. Quando creiamo la variabile y e assegniamo il valore di x, ora siamo in grado di sfruttare le varie proprietà di x che include il valore di dog, cioè "poodle". Questa sembra la stessa logica usata per i valori primitivi, ma diamo un’occhiata al nostro grafico handy-dandy qui sotto per vedere la differenza sottile, ma importante.

Sia x e y del punto a (e) indirizzo di memoria che contiene un riferimento all’oggetto

Ora, questo grafico sembra un po ‘ diverso da quando la nostra variabili x e y tenuto tipi di dati primitivi. In questa versione, vediamo che i valori per entrambi x e y non sono tipi di dati ma riferimenti a un indirizzo in memoria, lo stesso indirizzo in effetti! Ora diamo un’occhiata a cosa succede a x se vogliamo aggiungere una nuova proprietà di size per y

x ancora restituisce un oggetto, ma oggi è un’ulteriore proprietà di size anche! Di nuovo, questo perché sia x che y puntano allo stesso oggetto di riferimento, quindi tutte le modifiche apportate a una variabile saranno visibili nell’altra.

il Grafico illustra come un cambiamento in y aggiorna il valore di riferimento che è in comune con x

Per aiutarmi a ricordare questo concetto, mi piace pensare a dei valori di riferimento di una casa e le variabili come persone che vivono in quella casa. Tutti i residenti (variabili) possono dire “Ho una casa” e indicare la stessa casa. Se un singolo residente decide di voler dipingere la casa di colore giallo, allora tutti i residenti ora hanno una casa gialla perché è condivisa.

Diamo un’occhiata a un altro esempio che contiene una varietà di oggetti di riferimento.

In questo codice, iniziamo con una variabile person che contiene proprietà di name, agee hobbies. Quando stampiamo questo oggetto sulla console, otteniamo esattamente ciò che ci aspettiamo: lo stesso oggetto che abbiamo appena creato.

Successivamente, abbiamo una funzione chiamata changePerson che accetta un argomento, apporta alcune modifiche, quindi restituisce un oggetto. Quando creiamo la variabile thirdPerson, invochiamo la funzionechangePerson passando il nostro oggetto originale di person in esso. Il bit interessante è ciò che accade quando stampiamo di nuovo sulla console thirdPerson e person.

Si noti che console.log(thirdPerson) restituisce un oggetto completamente nuovo con nuove proprietà. Ora guarda cosa restituisce console.log(person). Questo è simile al nostro oggetto originale ma contiene nuovi valori di proprietà che sono stati introdotti nella nostra funzione changePerson.

Verifica dell’uguaglianza

Infine, diamo un’occhiata a come si comportano i tipi di dati primitivi e gli oggetti di riferimento con gli operatori di uguaglianza.

Quando si tratta di tipi di dati primitivi, non importa cosa si trova a destra del segno = purché i valori siano gli stessi. Possiamo vedere questo sopra con le variabili a e b che sono scritte in modo diverso ma valutano lo stesso valore quando usiamo ===, l’operatore di uguaglianza rigorosa.

È vero il contrario nel secondo esempio per doge cat. Sebbene possa sembrare che contengano valori identici, è un array e un oggetto di riferimento, il che significa che === sta controllando se sia dog che cat hanno lo stesso riferimento al valore in memoria. D’altra parte, bird === dog è vero perché condividono lo stesso oggetto di riferimento.

cane e uccello condividono lo stesso riferimento mentre cat non lo fa nonostante abbia un array identico

Conclusione

E questo conclude la nostra introduzione in pass by value vs pass by reference. Ci sono più argomenti che possono essere coperti sotto questo ombrello fondamentale, tra cui ciò che accade quando un riferimento viene sovrascritto o perso, come copiare un riferimento per creare un nuovo oggetto E fare in modo che la copia è una copia profonda, solo per citarne alcuni. Consiglierei di controllare le risorse che ho usato di seguito che approfondiscono alcuni di questi argomenti aggiuntivi in modo più dettagliato.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.