ha még nem ismeri a Javascriptet, akkor valószínű, hogy már belefutott néhány vicces viselkedésbe, amelyet ez a nyelv kínál (a kiállítás). Eleinte ezek a furcsa furcsaságok nevetségesnek és frusztrálónak tűnhetnek, de ígérem, hogy van egy módszer az őrület mögött.
szerény véleményem szerint az egyik legnehezebb akadály, amelyet le kell küzdeni, a különbség az érték szerinti átadás vs a referencia átadása között. Miért olyan trükkös ez a koncepció? Először is, biztosan elég messzire juthatsz anélkül, hogy igazán megértenéd, hogy a JavaScript hogyan működik együtt a primitív értékekkel és a referenciaértékekkel. Ez, és gyakrabban, mint nem, egy csomó hibát eredményez, amelyeket nehéz nyomon követni és bosszantó javítani. Másodszor, ez egy olyan koncepció, amely technikai interjúkban fog megjelenni, így ha nem érti, akkor hatalmas vörös zászlónak számít ellened.
ne félj, kedves olvasó!
primitív adattípusok
a JavaScript-ben az adattípusokat két különböző vödörre oszthatjuk, primitív adattípusokra és objektumokra.
hat primitív adattípus van a JavaScriptben: string
, number
, boolean
, undefined
, null
, és symbol
az ES6-tól.
a primitív adattípusok érték szerint kerülnek átadásra vagy másolásra, és megváltoztathatatlanok, ami azt jelenti, hogy a meglévő érték nem változtatható meg úgy, ahogy egy tömb vagy objektum képes. Vessünk egy pillantást az alábbi kódra, hogy ezt működés közben láthassuk.
itt két változót hoztunk létre, x = 10
és y = x
. Mivel a 10
egy szám és egy primitív érték, amikor a y = x
értéket állítjuk be, valójában átmásoljuk az értéket, azaz 10
, és hozzárendeljük a y
– hez. Ezt az alábbi táblázat segítségével is megjeleníthetjük.
ha megváltoztatnánk a x
értékét, azt látnánk, hogy a y
megtartja 10
értékét. Ez azért van, mert a primitív értékek másolódnak, így a y
értéke független a x
értékétől. Gondolj rá úgy, mintha fénymásolatot készítenél egy képről. A másolat elkészítése után két azonos kép van: egy eredeti és egy fax. Ha kettévágnánk az eredetit, csak az eredetit változtatnánk meg, és a fax pontosan ugyanaz maradna.
Referenciaobjektumok
az objektumokat viszont referenciaként adjuk át, és az érték egy helyére mutatnak a memóriában, nem magára az értékre. Vessünk egy pillantást erre a kódunkban.
primitív adattípusokra ebben a példában a x
most egy objektum, amely {dog: "poodle"}
– re mutat. Amikor létrehozzuk a y
változót, és x
értéket rendelünk hozzá, most már képesek vagyunk a x
különböző tulajdonságaira támaszkodni, amelyek tartalmazzák a dog
értékét, azaz "poodle"
. Úgy tűnik, hogy ez pontosan ugyanaz a logika, amelyet a primitív értékeknél használnak, de vessünk egy pillantást az alábbi praktikus-dandy diagramra, hogy lássuk a finom, de fontos különbséget.
objektumra való hivatkozást tárolja. Ebben a verzióban azt látjuk, hogy mind a x
, mind a y
értékei nem adattípusok, hanem a memóriában lévő címekre való hivatkozások, valójában ugyanaz a cím! Most vessünk egy pillantást arra, hogy mi történik x
ha hozzáadunk egy új tulajdonságot size
nak nek y
…
x
még mindig visszaad egy objektumot, de most van egy további tulajdonsága size
is! Ismét azért, mert mind a x
, mind a y
ugyanarra a referenciaobjektumra mutat, így az egyik változóban végrehajtott változtatások a másikban láthatók lesznek.
– vel megosztott referenciaértéket, hogy segítsen emlékezni erre a koncepcióra, szeretem a referenciaértékeket házként, a változókat pedig az abban a házban élő emberekként gondolni. Minden lakó (változó) mondhatja, hogy “van egy házam”, és ugyanarra a házra mutat. Ha egyetlen lakos úgy dönt, hogy sárgára akarja festeni a házat, akkor az összes lakónak most sárga háza van, mert megosztják.
vessünk egy pillantást még egy példára, amely különféle referenciaobjektumokat tartalmaz.
ebben a kódban egy person
változóval kezdjük, amely name
, age
és hobbies
tulajdonságokat tartalmaz. Amikor ezt az objektumot kinyomtatjuk a konzolra, pontosan azt kapjuk, amire számítunk — ugyanazt az objektumot, amelyet éppen létrehoztunk.
ezután van egy changePerson
nevű függvényünk, amely argumentumot vesz fel, néhány változtatást hajt végre, majd visszaad egy objektumot. Amikor létrehozzuk a thirdPerson
változót, meghívjuk achangePerson
függvényt azáltal, hogy átadjuk az eredeti person
objektumot. Érdekes, hogy mi történik, ha a thirdPerson
és person
konzolra nyomtatunk.
figyeljük meg, hogy console.log(thirdPerson)
visszatér egy teljesen új objektum új tulajdonságokkal. Most nézd meg, mi console.log(person)
visszatér. Ez hasonló az eredeti objektumunkhoz, de új tulajdonságértékeket tartalmaz, amelyeket a changePerson
függvényben vezettek be.
egyenlőség ellenőrzése
végül nézzük meg, hogyan viselkednek a primitív adattípusok és referenciaobjektumok az egyenlőség operátorokkal.
ha primitív adattípusokról van szó, nem számít, mi van a =
jeltől jobbra, mindaddig, amíg az értékek megegyeznek. Ezt láthatjuk a a
és b
változókkal, amelyek másképp vannak írva, de ugyanazt az értéket értékelik ,ha a ===
– et használjuk, a szigorú egyenlőség operátort.
az ellenkezője igaz a második példában dog
és cat
. Bár úgy tűnhet, hogy azonos értékeket tartalmaznak, a egy tömb és egy referenciaobjektum, ami azt jelenti, hogy a
===
ellenőrzi, hogy mind a dog
, mind a cat
azonos hivatkozást tartalmaz-e a memóriában lévő értékre. Másrészt a bird === dog
igaz, mert ugyanazt a referenciaobjektumot használják.
következtetés
és ezzel lezárjuk a bevezetésünket a pass by value vs pass by reference-be. Több téma is lefedhető ezen ernyő alatt alapvető, beleértve azt is, hogy mi történik, ha egy hivatkozást felülírnak vagy elvesznek, hogyan lehet másolni egy hivatkozást egy új objektum létrehozásához, és győződjön meg arról, hogy a másolat mély másolat, csak néhányat említve. Azt javaslom, hogy nézze meg az alább használt erőforrásokat, amelyek részletesebben foglalkoznak ezekkel a további témákkal.