zapouzdření v JavaScriptu

toto bude můj poslední příspěvek v sérii „JavaScript for (C/)Al Developers“ dnes. Kdybych pokračoval v blogování o téměř čistých věcech JavaScriptu,můžete se rozumně zeptat, jestli je to ve skutečnosti blog NAV nebo JavaScript. Je to stále NAV, a zatímco věci, o kterých se chystám psát, jsou čistě konceptem JavaScriptu, považuji to za velmi relevantní pro všechny vývojáře doplňků control. Tak, podrž mi pivo, a snaž se se mnou o další.

jednou ze stížností, které často slyším o JavaScriptu, je to, že v JavaScriptu není zapouzdření. To je téměř úplně pravda, až na to, že je to zcela nepravdivé.

kde je problém na prvním místě a jaké je řešení? Pojďme se do toho ponořit.

problém

Představte si, že deklarujete Konstruktor. Představte si na chvíli, že jsme ve světě ES5 (které bohužel musíme použít, pokud chceme, aby naše kontrolní doplňky byly plně kompatibilní se všemi platformami, na kterých jsou podporovány NAV i Business Central).

Toto je můj kód:

očividně, to ukazuje 42, což je můj současný věk.

brzy budu mít narozeniny, takže by to ukázalo 43:

Nyní, zatímco já bych naprosto rád, aby bylo možné udělat něco takového v reálném životě:

… to se nestane. Ve slušném objektově orientovaném světě by „věk“ měl být zapouzdřenou vlastností a neměli byste být schopni volat vjeko.věk = 25 vůbec. C# a „normální“ objektově orientované jazyky mají koncept zapouzdření, zvládnou to pomocí soukromých polí, ale JavaScript nemá koncept soukromého. Vše, co je definováno uvnitř konstruktoru objektů (nebo později na instanci konstruovaného objektu), je plně přístupné všem kódům, které mají přístup k této instanci. V mém příkladu výše, kdokoli může nastavit věk a dostat se s ním pryč.

Dalo by se říci, že JavaScript nemá zapouzdření. A jak jsem řekl výše, úplně byste se mýlil.

řešení

jak je zřejmé, že nemůžeme prohlásit nic jako soukromé přímo, stále existují věci, které můžeme použít. Jeden krásný koncept, který se hodí, se nazývá uzávěry. Uzávěry jsou podrobně vysvětleny na milionu blogů, dokumentační weby, a příklady kódu po celém internetu, a můžete si z nich vygooglit bejesus svým vlastním tempem, takže se nebudu ponořit do vysvětlování uzávěrů zde. Jednoduše skočím přímo do jejich použití při řešení problému zapouzdření.

existují alespoň dva způsoby, jak byste to mohli zvládnout. Pojďme nejprve udělat jasnější: přístupovou funkci.

Představte si svět bez vlastností, kde nemůžete dělat objekt.vlastnost = hodnota (jako vjeko.věk = 25 v našem případě, stejně jako bych to úplně miloval!). V tomto světě byste měli funkce getter a setter:

(na chvíli ignorujte skutečnost, že to stále používám.věk pro „zapouzdření „“vlastnosti“)

je zřejmé, že byste je mohli nazvat takto:

pak, pokud jste chtěli mít věk pouze pro čtení, jednoduše byste upustili od funkce setage setter. Pokud tohle.věk byl opravdu soukromý (což není), to by pro vás udělalo trik. Problém je v tom, že nic z toho není soukromé, je přístupné každému, kdo má přístup k jakékoli instanci objektu. Je to tak veřejné, jak to jen jde.

abychom tento problém vyřešili, musíme nejprve přesunout deklaraci funkce getter z prototypu do instance. Členové prototypu jsou nejblíže tomu, co bychom nazvali statickým v C#, i když za běhu mají určité behaviorální rysy statických i instančních členů. Nicméně, pojďme nejprve přesunout Člen od prototypu, a na instanci:

to řeší pouze první část problému, skutečnost, že getAge byl definován spíše na prototypu než na instanci. Nicméně, s jednoduchou změnou, jako je tato:

… problém řešíme úplně:

věk je nyní plně zapouzdřen. Můžete k němu přistupovat prostřednictvím funkce getter, ale nemůžete jej nastavit přímo, protože je přístupný pouze v rozsahu uzavření tohoto.funkce instance getAge.

Chcete-li plně implementovat třídu Person, musíte přesunout funkci growOlder z prototypu do instance:

a to funguje přesně tak, jak chcete, aby to fungovalo:

ale proč to funguje? Funguje to kvůli uzavírkám. Parametr age z konstruktoru byl zachycen v rozsahu uzavření funkcí getAge i growOlder, což vám umožňuje přístup k jeho hodnotě z obou těchto funkcí, ale znemožňuje to nikomu jinému, kdekoli jinde.

ještě lepší řešení

dalo by se říci, že k němu nechcete přistupovat pomocí funkce getteru a že potřebujete plnohodnotnou syntaxi vlastností pouze pro čtení. Chcete, aby váš věk byl pouze pro čtení a zapouzdřen současně. Mám tě! JavaScript to nemůže zapouzdřit! Až na to, že to absolutně může.

oslovil jsem objekt.defineProperty metoda v mém předchozím příspěvku, a pokud si ji přečtete, můžete okamžitě vidět, jak ji lze použít zde.

pojďme tedy definovat vlastnost instance pouze pro čtení třídy Person:

tak. Nebolelo to. A funguje to:

tak tady to máte. Plnohodnotné zapouzdření v JavaScriptu, které vám pomůže psát dobrý, izolovaný kód a vzít si kontrolní doplňky na skutečnou úroveň kick-a$$.

Šťastný JavaScripting a doufám, že dostanu více času na blog o dalších skvělých a užitečných tipech a tricích JavaScriptu pro vývojáře (C/)AL.

Napsat komentář

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