hvis du er ny til JavaScript, er chancerne for, at du allerede har kørt ind i noget af den sjove opførsel, dette sprog har at tilbyde (udstilling a). Først, disse underlige særheder kan virke latterlige og frustrerende, men jeg lover, at der er en metode bag al den galskab.
en af de sværeste forhindringer at overvinde, efter min ydmyge mening, er forskellen mellem at passere efter værdi vs at passere efter reference. Hvorfor er dette koncept så vanskeligt? Til at begynde med kan du helt sikkert komme temmelig langt uden virkelig at forstå, hvordan JavaScript interagerer med primitive værdier og referenceværdier. Dette kan, og oftere end ikke, vil resultere i masser af fejl, der er svære at spore og irriterende at rette. For det andet er dette et koncept, der vil komme op i tekniske samtaler, så ikke at forstå det vil tælle som et stort rødt flag mod dig.
Frygt ikke, kollega læser! Lad uddannelsen begynde …
Primitive datatyper
i JavaScript kan vi opdele datatyper i to forskellige spande, primitive datatyper og objekter.
der er seks primitive datatyper i JavaScript: string
, number
, boolean
, undefined
, null
, og symbol
fra ES6.
Primitive datatyper overføres eller kopieres efter værdi og er uforanderlige, hvilket betyder, at den eksisterende værdi ikke kan ændres, som et array eller et objekt kan. Lad os se på koden nedenfor for at se dette i aktion.
her har vi oprettet to variabler, x = 10
og y = x
. Da 10
er et tal og en primitiv værdi, når vi indstiller y = x
, kopierer vi faktisk værdien, dvs. 10
, og tildeler den til y
. Vi kan også visualisere dette ved hjælp af nedenstående diagram.
hvis vi skulle ændre værdien af x
, ville vi se, at y
bevarer sin værdi på 10
. Igen skyldes dette, at primitive værdier kopieres, så y
‘s værdi er uafhængig af x
‘s værdi. Tænk på det som at lave en fotokopi af et billede. Når du har lavet kopien, har du to identiske billeder: en original og en faksimile. Hvis du skulle skære originalen i halvdelen, ville kun originalen blive ændret, og faksimilen ville forblive nøjagtig den samme.
referenceobjekter
objekter sendes derimod som reference og peger på en placering i hukommelsen for værdien, ikke selve værdien. Lad os se på dette i vores kode.
i dette eksempel er x
nu et objekt, der peger på {dog: "poodle"}
. Når vi opretter variablen y
og tildeler den værdien x
, er vi nu i stand til at udnytte de forskellige egenskaber af x
, som inkluderer værdien for dog
, dvs. "poodle"
. Dette virker som den nøjagtige samme logik, der bruges til primitive værdier, men lad os se på vores handy-dandy-diagram nedenfor for at se den subtile, men vigtige forskel.
nu ser dette diagram lidt anderledes ud end da vores variabler x
og y
holdt primitive datatyper. I denne version ser vi, at værdierne for både x
og y
ikke er datatyper, men henvisninger til en adresse i hukommelsen, faktisk den samme adresse! Lad os nu se på, hvad der sker med x
hvis vi tilføjer en ny ejendom på size
tily
…
x
returnerer stadig et objekt, men nu har det en ekstra egenskab på size
også! Igen skyldes dette, at både x
og y
peger på det samme referenceobjekt, så eventuelle ændringer foretaget i en variabel vil være synlige i den anden.
for at hjælpe mig med at huske dette koncept, kan jeg godt lide at tænke på referenceværdier som et hus og variablerne som mennesker, der bor i det hus. Alle beboerne (variabler) kan sige “jeg har et hus” og pege på det samme hus. Hvis en enkelt beboer beslutter, at de vil male huset gult, så har alle beboerne nu et gult hus, fordi det deles.
lad os se på endnu et eksempel, der indeholder en række referenceobjekter.
i denne kode starter vi med en variabel person
, der indeholder egenskaber på name
, age
og hobbies
. Når vi udskriver dette objekt til konsollen, får vi præcis det, vi forventer — det samme objekt, vi lige har oprettet.
Dernæst har vi en funktion kaldet changePerson
, der tager et argument, foretager et par ændringer og derefter returnerer et objekt. Når vi opretter variablen thirdPerson
, påberåber vichangePerson
– funktionen ved at føre vores oprindelige objekt person
ind i det. Det interessante er, hvad der sker, når vi udskriver til konsollen thirdPerson
og person
igen.
Bemærk, at console.log(thirdPerson)
returnerer et helt nyt objekt med nye egenskaber. Se nu på, hvad console.log(person)
vender tilbage. Dette ligner vores oprindelige objekt, men det indeholder nye egenskabsværdier, der blev introduceret i vores changePerson
funktion.
kontrol af ligestilling
lad os endelig se på, hvordan primitive datatyper og referenceobjekter opfører sig med ligestillingsoperatører.
når det kommer til primitive datatyper, betyder det ikke noget, hvad der er til højre for =
– tegnet, så længe værdierne er de samme. Vi kan se dette ovenfor med variabler a
og b
, som er skrevet forskelligt, men evalueres til den samme værdi, når vi bruger ===
, den strenge ligestillingsoperatør.
det modsatte er tilfældet i det andet eksempel for dog
og cat
. Selvom det kan se ud til, at de indeholder identiske værdier, er et array og et referenceobjekt, hvilket betyder, at
===
kontrollerer, om både dog
og cat
har den samme reference til værdien i hukommelsen. På den anden side er bird === dog
sandt, fordi de deler det samme referenceobjekt.
konklusion
og det afslutter vores introduktion til pass by value vs pass by reference. Der er flere emner, der kan dækkes under denne paraply grundlæggende, herunder hvad der sker, når en reference overskrives eller går tabt, hvordan man kopierer en henvisning for at oprette et nyt objekt og sørge for, at kopien er en dyb kopi, bare for at nævne nogle få. Jeg vil anbefale at tjekke de ressourcer, jeg brugte nedenfor, som går nærmere ind på nogle af disse yderligere emner.