Pass by Value vs Pass by Reference v JavaScriptu

pokud jste v JavaScriptu nováčkem, je pravděpodobné, že jste již narazili na některé vtipné chování, které tento jazyk nabízí (exponát a). Nejprve, tyto podivné vtípky se mohou zdát směšné a frustrující, ale slibuji, že za vším tím šílenstvím je metoda.

jednou z nejtěžších překážek, které je třeba překonat, je podle mého skromného názoru rozdíl mezi procházením hodnotou a procházením odkazem. Proč je tento koncept tak složitý? Pro začátečníky, určitě se můžete dostat docela daleko, aniž byste skutečně pochopili, jak JavaScript interaguje s primitivními hodnotami a referenčními hodnotami. To může, a častěji než ne, bude mít za následek spoustu chyb, které je těžké vystopovat a nepříjemné je opravit. Za druhé, jedná se o koncept, který se objeví v technických rozhovorech, takže jeho nepochopení se bude počítat jako obrovská červená vlajka proti vám.

nebojte se, kolegové čtenáři!

primitivní datové typy

v JavaScriptu můžeme rozdělit datové typy na dva různé kbelíky, primitivní datové typy a objekty.

graf znázorňující primitivní datové typy nebo hodnoty a typy objektů nebo referenční hodnoty

v JavaScriptu je šest primitivních datových typů: string, number, boolean, undefined, null, a symbol od ES6.

primitivní datové typy jsou předávány nebo kopírovány podle hodnoty a jsou neměnné, což znamená, že existující hodnotu nelze změnit tak, jak může pole nebo objekt. Podívejme se na níže uvedený kód, abychom to viděli v akci.

vytvořeno pomocí jsbin.com

zde jsme vytvořili dvě proměnné, x = 10 a y = x. Protože 10 je číslo a primitivní hodnota, když nastavíme y = x, skutečně zkopírujeme hodnotu, tj. 10, a přiřadíme ji y. Můžeme si to také představit pomocí níže uvedené tabulky.

pokud bychom změnili hodnotu x, viděli bychom, že y si zachovává svou hodnotu 10. Opět je to proto, že jsou zkopírovány primitivní hodnoty, takže hodnota yje nezávislá na hodnotě x. Přemýšlejte o tom jako o fotokopii obrázku. Po vytvoření kopie máte dva identické obrázky: originál a faksimile. Pokud byste originál rozřezali na polovinu, změnil by se pouze originál a faksimile by zůstal úplně stejný.

přepsali jsme hodnotu x, ale y zůstává stejný

referenční objekty

objekty jsou naproti tomu předávány odkazem a ukazují na místo v paměti pro hodnotu, nikoli samotnou hodnotu. Podívejme se na to v našem kódu.

proměnné x a y nyní ukazují spíše na objekty než na primitivní datové typy

v tomto příkladu je x nyní objekt ukazující na {dog: "poodle"}. Když vytvoříme proměnnou y a přiřadíme jí hodnotu x, můžeme nyní využít různé vlastnosti x, které obsahují hodnotu pro dog, tj. "poodle". Vypadá to jako přesně stejná logika používaná pro primitivní hodnoty, ale podívejme se na náš šikovný graf níže, abychom viděli jemný, ale důležitý rozdíl.

x I y ukazují na (vytvořenou) adresu v paměti, která ukládá odkaz na objekt

nyní tento graf vypadá trochu jinak, než když naše proměnné x a y držely primitivní datové typy. V této verzi vidíme, že hodnoty pro x a y nejsou datové typy, ale odkazy na adresy v paměti, ve skutečnosti stejnou adresu! Nyní se podívejme, co se stane s x, pokud přidáme novou vlastnost size y

x stále vrací objekt, ale nyní má další vlastnost size také! Opět je to proto, že jak x, tak y ukazují na stejný referenční objekt, takže jakékoli změny provedené v jedné proměnné budou viditelné v druhé.

graf ukazuje, jak změna v y aktualizuje referenční hodnotu, která je sdílena s x

abych si vzpomněl na tento koncept, rád přemýšlím o referenčních hodnotách jako o domě a proměnných jako o lidech, kteří žijí v tomto domě. Všichni obyvatelé (proměnné) mohou říci „mám dům“ a ukázat na stejný dům. Pokud se jeden obyvatel rozhodne, že chce dům namalovat žlutě, pak všichni obyvatelé mají nyní žlutý dům, protože je sdílen.

podívejme se na další příklad, který obsahuje různé referenční objekty.

v tomto kódu začneme proměnnou person, která obsahuje vlastnosti name, age a hobbies. Když vytiskneme tento objekt do konzoly, dostaneme přesně to — co očekáváme-stejný objekt, který jsme právě vytvořili.

dále máme funkci nazvanou changePerson, která vezme argument, provede několik změn a vrátí objekt. Když vytvoříme proměnnou thirdPerson, vyvoláme funkcichangePerson předáním našeho původního objektu person do něj. Zajímavé je, co se stane, když znovu vytiskneme na konzoli thirdPerson a person.

Všimněte si, že console.log(thirdPerson) vrací zcela nový objekt s novými vlastnostmi. Nyní se podívejte na to, co console.log(person) vrací. Toto je podobné našemu původnímu objektu, ale obsahuje nové hodnoty vlastností, které byly zavedeny v naší funkci changePerson.

kontrola rovnosti

nakonec se podívejme, jak se chovají primitivní datové typy a referenční objekty s operátory rovnosti.

pokud jde o primitivní datové typy, nezáleží na tom, co je napravo od znaménka =, pokud jsou hodnoty stejné. Můžeme to vidět výše s proměnnými a a b, které jsou psány odlišně, ale vyhodnocují se na stejnou hodnotu, když použijeme ===, striktní operátor rovnosti.

opak je pravdou ve druhém příkladu pro dog a cat. I když se může zdát, že obsahují stejné hodnoty, je pole a referenční objekt, což znamená, že === kontroluje, zda oba dog a cat mají stejný odkaz na hodnotu v paměti. Na druhou stranu bird === dog je pravda, protože sdílejí stejný referenční objekt.

pes a pták sdílejí stejný odkaz, zatímco kočka nemá, přestože má identické pole

závěr

a to uzavírá náš úvod do pass by value vs pass by reference. Existuje více témat, která mohou být pokryta pod tímto deštníkem základní, včetně toho, co se stane, když je odkaz přepsán nebo ztracen, jak zkopírovat odkaz pro vytvoření nového objektu a ujistit se, že kopie je hluboká kopie, jen abychom jmenovali alespoň některé. Doporučil bych vyzkoušet zdroje, které jsem použil níže, které se podrobněji zabývají některými z těchto dalších témat.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.