Articles

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.

(úvod/introspekce.js)

Ve výše uvedeném programu, jsme použili typeofinstanceof 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.

(introduction/proxy.js)

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í gettersetters 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.

(úvod/funkce-změna.js)

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í.

(úvod/readonly-objekt.js)

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).

(úvod/valueof.js)

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.salary200. 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ž valueOfstring 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.

(úvod/symbol-toPrimitive.js)

💡 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ů.