stručný úvod do Metaprogramming v JavaScript
Úvahy
Odraz, mě nemá ráda „generování kódu“, je proces, změnit základní mechaniky jazyka. Reflexe se může stát v době kompilace nebo za běhu, ale budeme se držet odrazu běhu, když mluvíme o JavaScriptu, takže reflexe kompilace nebude možná. Zde diskutované pojmy by však mohly být použitelné i pro kompilovaný jazyk.
jak jsme pochopili, že reflexe je o změně základní mechaniky jazyka, byla rozdělena do tří hlavních kategorií, viz. introspekce, přímluva a modifikace.
introspekce
introspekce je proces analýzy programu. Pokud můžete říct, co program dělá, můžete jej upravit podle vašich představ. I když některé programovací jazyky nepodporují generování kódu nebo modifikaci kódu funkce, ale s největší pravděpodobností umožňují introspekci.
jednoduchým příkladem introspekce by bylo použití operátorů typeof
nebo instanceof
v JavaScriptu. typeof
vrací aktuální typ dat hodnota (nebo výraz, který vrací hodnotu), zatímco instanceof
výnosy true
nebo false
pokud LHS hodnota je instance RHS třídy. Uvidíme je v akci.
Ve výše uvedeném programu, jsme použili typeof
instanceof
operátoři v coerce
funkce čichat datový typ příchozí value
. Toto je základní ukázka introspekce. Jazyk speciálně navržený pro metaprogramování však může poskytnout některé výkonné nástroje pro introspekci.
pomocí operátoru in
můžete zkontrolovat, zda v objektu existuje vlastnost. isNaN
globální funkce kontroluje, zda je objekt NaN
. Tam jsou některé statické metody postaven kolem Object
zkontrolujte, zda hodnoty Object
typu jako Object.isFrozen(value)
zkontrolujte, zda value
je zmrazené nebo Object.keys(value)
získat majetek jména value
objekt.
až do ES5 jsme měli tyto operátory a tyto metody, se kterými jsme mohli pracovat. V ES2015 (ES6), JavaScript, představil Reflect
objekt, který nabízí některé statické metody (stejně jako Object
), ale speciálně pro sebepozorování. Protože máme samostatnou lekci o Reflect
, Jsou zde diskutovány tyto metody.
přímluva
přímluva je proces zasahování do procesů JavaScriptu a úpravy standardního chování procesu. JavaScript poskytuje skvělé nástroje pro přímluvu, z nichž jeden je Proxy
.
Proxy
třída byla zavedena v ES2015 (ES6) zachytit (zasahovat) základní JavaScript operace kolem objektů, jako jsme viděli výše, ale v mnohem hezčí cesta. Máme samostatnou lekci o Proxy
(již brzy), ale ve zkratce, Proxy
obtéká zachycitelnou logiku kolem objektu.
var targetWithProxy = new Proxy(target, handler);
, target
je objekt a handler
je interceptor. handler
je také prostý objekt JavaScriptu, ale s některými smysluplnými poli. For example, handler.get
would be a function that returns a custom value when target.prop
(here, prop
is any property) is accessed.
Proxy is a great way to provide abstractions over your not-so-public data. Například, ve výše uvedeném programu, jsme poskytli abstrakce přes target
objekt a přizpůsobit tak, jak by to mělo prezentovat veřejnosti.
Některé přímluvu bylo možné v ES5, stejně jako pomocí getter
setters
vlastnost popisovače ale to by mělo za následek mutace target
objekt. Proxy
poskytuje mnohem čistší způsob, jak dosáhnout přímluvy bez nutnosti měnit původní objekt (target
).
modifikace
modifikace označuje modifikaci chování programu mutací. V případě přímluvy jsme zachytili standardní procesy JavaScriptu pouze přidáním záchytné logiky mezi cíl a přijímač bez poškození cíle. V tomto případě měníme chování samotného cíle tak, aby vyhovovalo přijímači.
přepsání implementace funkce by bylo dobrým příkladem modifikace. Například, pokud je funkce navržena tak, aby se chovala určitým způsobem, ale chceme podmíněně něco jiného, můžeme to udělat tím, že navrhneme vlastní funkci. Podívejme se na příklad.
Ve výše uvedeném příkladu jsme vytvořili funkci, která přepíše sám s novou funkcí provádění. To by byl nejtvrdší příklad modifikace, ale máme jiné, možná smysluplnější případy použití.
Ve výše uvedeném příkladu, jsme použili Object.defineProperty()
metoda změnit výchozí vlastnost popisovač name
majetek tak, aby to jen pro čtení. Můžete také použít metodu Object.freeze()
k uzamčení celého objektu, abyste se vyhnuli jakýmkoli mutacím.
některé přímluvy se mohou stát modifikacemi, jak můžete z výše uvedeného příkladu. Nastavením writable:false
v objektu deskriptor objektu, proto mutuje objektu (vnitřní provedení), máme založený na přiřazení hodnoty provozu.
Pokud nejste obeznámeni s metodou valueOf
, používá se k vynucení objektu na primitivní hodnotu. Takže pokud mám objekt a má valueOf
metoda na sobě nebo na svém řetězci prototypu, pak tato metoda se nazývá JavaScript, když se snaží provádět aritmetické operace. Ve výchozím nastavení má Object
metodu valueOf
, která se vrací (objekt).
Jak můžete vidět ve výše uvedeném příkladu, emp1/10
vyústil v NaN
, protože objekt nemůže být rozděleno jako přirozená čísla. Ale později jsme přidali valueOf
metoda Employee
třídu, která vrací salary
hodnoty objektu. Proto emp2/10
je vrácen 200
, protože emp2.salary
200
. Podobně, emp3/10
je vrácen 300
jak jsme přidali valueOf
metoda přímo na emp3
.
Takže na každý krok ve výše uvedeném příkladu jsme zasahují jak objekt je prezentován na standardní JavaScript provozu a změna jeho chování našich představ. To není nic jiného než přímluva.
V ES2015 (ES6), JavaScript zavedl nový primitivní datový typ, který je symbol
. Není to nic, co jsme viděli dříve, a nemůže být reprezentován v doslovné podobě. Může být konstruován pouze voláním funkce Symbol
.
var sym1 = Symbol();
var sym2 = Symbol();
var sym3 = Symbol('description'); // description for debugging aidsym1 === sym2 // false
sym1 === sym2 // falsetypeof sym1 // 'symbol'console.log( sym1 ); // 'Symbol()'
console.log( sym3 ); // 'Symbol(description)'
Ve zkratce, to produkuje jedinečné hodnoty, které mohou být také použity jako pravidelné objektu klíče pomocí obj
zápis key
by to být symbol.
var key = Symbol();var obj = {
name: 'Ross',
: 200
};console.log( obj.name ); // 'Ross'
console.log( obj ); // 200
Object.keys(obj); // obj = 300;
protože jsou jedinečné, neexistuje způsob, jak vytvořit duplicitní symbol náhodou. Každý nový symbol je unikátní (vytvořené pomocí Symbol()
), které znamená, že pokud chcete použít stejný symbol, je třeba uložit, že v proměnné a stane se, že proměnná kolem odkazovat na stejný symbol.
v valueOf
příklad, můžete zjistit problém, pokud nejsme opatrní nebo vědomi. Jelikož valueOf
string
majetku (jako v emp3
) , každý se může přepsat náhodně, nebo někdo, kdo neví, o valueOf
by mohla v plánu používat jej pro jeho/její vlastní potřebu přemýšlet „co je v názvu?“.
vzhledem k tomu, že symboly mohou být také použity jako klíče objektů, JavaScript poskytl některé globální symboly, které by měly být použity jako klíče objektů pro některé standardní operace JavaScriptu. Protože tyto symboly jsou vývojáři dobře známy, nazývají se „známé Symboly“. Tyto známé Symboly jsou veřejnosti vystaveny jako statické vlastnosti funkce Symbol
.
jedním ze známých symbolů je Symbol.toPrimitive
který by měl být použit jako klíč objektu k získání jeho primitivní hodnoty. Ano, myslíte správně, je to náhrada metody valueOf
a je preferována.
💡
toPrimitive
metoda dělá více než jen vrací číselnou hodnotu objektu. Přečtěte si prosím lekce symbolů, abyste se o tom dozvěděli více.
JavaScript poskytuje mnoho takových známých symbolů pro zachycení a úpravu výchozího chování JavaScriptu kolem objektů. Budeme o tom mluvit a symboly obecně v lekci symbolů.