hvis Du er ny Til JavaScript, sjansene er du allerede har kjørt inn i noen av de morsomme atferd dette språket har å tilby (utstilling A). I begynnelsen kan disse rare quirks virke latterlig og frustrerende, men jeg lover at det er en metode bak all den galskapen.
En av de vanskeligste hindrene å overvinne, i min ydmyke mening, er forskjellen mellom bestått av verdi vs bestått av referanse. Hvorfor er dette konseptet så vanskelig? For det første kan du sikkert komme ganske langt uten å forstå hvordan JavaScript samhandler med primitive verdier og referanseverdier. Dette kan, og oftere enn ikke, vil resultere i massevis av feil som er vanskelig å spore opp og irriterende å fikse. For det andre er dette et konsept som kommer opp i tekniske intervjuer, så ikke forstå det vil telle som et stort rødt flagg mot deg.
Frykt ikke, kjære leser! La utdanningen begynne…
Primitive Datatyper
I JavaScript kan vi dele datatyper i to forskjellige bøtter, primitive datatyper og objekter.
det er seks primitive datatyper I JavaScript: string
, number
, boolean
, undefined
, null
, og symbol
som AV ES6.
Primitive datatyper sendes eller kopieres etter verdi og er uforanderlige, noe som betyr at den eksisterende verdien ikke kan endres slik en matrise eller et objekt kan. La oss ta en titt på koden nedenfor for å se dette i aksjon.
her har vi laget to variabler, x = 10
og y = x
. Siden 10
er et tall og en primitiv verdi, når vi setter y = x
kopierer vi faktisk verdien, dvs. 10
, og tilordner den til y
. Vi kan også visualisere dette ved hjelp av diagrammet nedenfor.
hvis vi skulle endre verdien av x
, ville vi se at y
beholder verdien av 10
. Igjen er dette fordi primitive verdier kopieres, så y
‘s verdi er uavhengig av x
‘s verdi. Tenk på det som å lage en kopi av et bilde. Etter at du har laget kopien, har du to identiske bilder: en original og en faksimile. Hvis du skulle kutte originalen i halvparten, ville bare originalen bli endret og faksimilen ville forbli nøyaktig den samme.
Referanseobjekter
Objekter, derimot, sendes ved referanse og peker til et sted i minnet for verdien, ikke selve verdien. La oss ta en titt på dette i vår kode.
i dette eksemplet er x
nå et objekt som peker på {dog: "poodle"}
. Når vi lager variabelen y
og tilordner den verdien av x
, kan vi nå tappe inn i de forskjellige egenskapene til x
som inkluderer verdien for dog
, dvs. "poodle"
. Dette virker som nøyaktig samme logikk som brukes for primitive verdier, men la oss ta en titt på vår handy-dandy diagrammet nedenfor for å se den subtile, men viktig forskjell.
nå ser dette diagrammet litt annerledes ut enn når våre variabler x
og y
holdt primitive datatyper. I denne versjonen ser vi at verdiene for både x
og y
ikke er datatyper, men referanser til adresser i minnet, den samme adressen faktisk! La oss nå se på hva som skjer med x
hvis vi legger til en ny egenskap av size
til y
…
x
returnerer fortsatt et objekt, men nå har det en ekstra egenskap på size
også! Igjen er dette fordi både x
og y
peker på det samme referanseobjektet, så eventuelle endringer i en variabel vil være synlige i den andre.
For å hjelpe meg med å huske dette konseptet, liker jeg å tenke på referanseverdier som et hus og variablene som folk som bor i det huset. Alle beboerne (variabler) kan si «jeg har et hus» og peke på samme hus. Hvis en enkelt beboer bestemmer seg for at de vil male huset gult, så har alle beboerne nå et gult hus fordi det deles.
La oss ta en titt på et annet eksempel som inneholder en rekke referanseobjekter.
i denne koden starter vi med en variabel person
som inneholder egenskaper name
, age
og hobbies
. Når vi skriver ut dette objektet til konsollen, får vi akkurat det vi forventer-det samme objektet vi nettopp opprettet.
Deretter har vi en funksjon kalt changePerson
som tar inn et argument, gjør noen endringer, og returnerer deretter et objekt. Når vi lager variabelen thirdPerson
, påkaller vi changePerson
– funksjonen ved å sende vårt opprinnelige objekt person
inn i det. Den interessante biten er hva som skjer når vi skriver ut til konsollen thirdPerson
og person
igjen.
Legg Merke til at console.log(thirdPerson)
returnerer et helt nytt objekt med nye egenskaper. Se nå på hva console.log(person)
returnerer. Dette ligner på vårt opprinnelige objekt, men det inneholder nye eiendomsverdier som ble introdusert i vår changePerson
– funksjon.
Se Etter Likestilling
Til Slutt, La Oss Se på hvordan primitive datatyper og referanseobjekter oppfører seg med likestillingsoperatører.
når det gjelder primitive datatyper, spiller det ingen rolle hva som er til høyre for =
– tegnet så lenge verdiene er de samme. Vi kan se dette ovenfor med variabler a
og b
som er skrevet annerledes, men evaluerer til samme verdi når vi bruker ===
, den strenge likestillingsoperatøren.
det motsatte er sant i det andre eksemplet for dog
og cat
. Mens det kan se ut til at de inneholder identiske verdier, er en matrise og et referanseobjekt, noe som betyr at
===
sjekker for å se om både dog
og cat
har samme referanse til verdien i minnet. På den annen side er bird === dog
sant fordi de deler samme referanseobjekt.
Konklusjon
og det avslutter vår introduksjon til pass by value vs pass by reference. Det er flere emner som kan dekkes under denne paraplyen grunnleggende, inkludert hva som skjer når en referanse er overskrevet eller tapt, hvordan kopiere en referanse for å opprette et nytt objekt OG sørge for at kopien er en dyp kopi, bare for å nevne noen. Jeg vil anbefale å sjekke ut ressursene jeg brukte under som går inn i noen av disse ekstra emnene i større detalj.