Articles

En kort introduksjon Til Metaprogrammering i JavaScript

Refleksjon

Refleksjon, unliked «kodegenerering», er en prosess for å endre den underliggende mekanikken i språket. Refleksjon kan skje ved kompileringstid eller ved kjøretid, men vi vil holde fast med runtime reflection som Vi snakker om JavaScript, så kompileringstid refleksjon vil ikke være mulig. Imidlertid kan begreper diskutert her også gjelde for et kompilert språk.Som vi har forstått at refleksjonen handler om å endre den underliggende mekanikken til språket, har den blitt delt inn i tre hovedkategorier, nemlig. introspeksjon, forbønn og modifikasjon.

Introspeksjon

Introspeksjon er prosessen med å analysere programmet. Hvis du kan fortelle hva programmet gjør, kan du endre det som per dine likings. Selv om noen programmeringsspråk ikke støtter kodegenerering eller kodemodifikasjonsfunksjoner, men de tillater sannsynligvis introspeksjon.

et enkelt eksempel på introspeksjon ville være å bruketypeof ellerinstanceof operatører I JavaScript. typeof returnerer gjeldende datatype for en verdi (eller et uttrykk som returnerer en verdi) mensinstanceof returnerertrue ellerfalse hvis lhs-verdien er en forekomst AV RHS-klassen. La oss se dem i aksjon.

(introduksjon/introspeksjon.js)

i programmet ovenfor har vi brukt typeof og instanceof operatører i coerce – funksjonen for å snuse datatypen for innkommende value. Dette er den grunnleggende demonstrasjonen av introspeksjon. Et språk som er spesielt utviklet for metaprogrammering, kan imidlertid gi noen kraftige introspeksjonsverktøy.

du kan bruke operatorenin for å sjekke om det finnes en egenskap i objektet. isNaN global funksjon kontrollerer om objektet er NaN. Det er noen statiske metoder bygget rundt Object for å inspisere verdier av Object type som Object.isFrozen(value) for å sjekke om value er frosset eller Object.keys(value) for å få egenskapsnavnene til value – objektet.

TIL ES5 hadde vi disse operatørene og disse metodene å jobbe med. I ES2015 (ES6) introduserte JavaScript Reflect objekt som gir noen statiske metoder (akkurat som Object), men spesielt designet for introspeksjon. Siden vi har en egen leksjon på Reflect, diskuteres disse metodene der.

Forbønn

Forbønn er prosessen med å gripe Inn I JavaScript-prosessene og endre prosessens standardadferd. JavaScript gir gode verktøy for forbønn hvorav den ene er Proxy.

Proxyklassen ble introdusert I ES2015 (ES6) for å fange opp (gripe inn) grunnleggende JavaScript-operasjoner rundt objekter akkurat som vi har sett ovenfor, men på en mye bedre måte. Vi har en egen leksjon på

Proxy(kommer snart), men i et nøtteskall,Proxybryter en avskjærbar logikk rundt et objekt.

var targetWithProxy = new Proxy(target, handler);

her er target objektet og handler er interceptor. handler er også et Vanlig JavaScript-objekt, men med noen meningsfulle felt. 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. For eksempel, i programmet ovenfor har vi gitt abstraksjoner over target objekt og tilpasset hvordan det skal presentere seg for publikum.

noen forbønn var mulig I ES5, så vel som å bruke getter og setters på egenskapsbeskrivelser, men det ville resultere i mutasjonen av target objektet. Proxy gir en mye renere måte å oppnå forbønn uten å måtte endre det opprinnelige objektet (target).

Modifikasjon

Modifikasjon refererer til modifikasjonen av programadferd gjennom mutasjon. I tilfelle av forbønn, vi bare snappet opp standard JavaScript prosesser ved å legge en avskjære logikk mellom målet og mottakeren uten å skade målet. I dette tilfellet modifikasjon, endrer vi oppførselen til målet selv så passer mottakeren.

Å Overstyre en funksjonsimplementering ville være et godt eksempel på modifikasjon. For eksempel, hvis en funksjon er utformet for å oppføre seg på en bestemt måte, men vi vil ha noe annet betinget, kan vi gjøre det ved å designe en selvstyrende funksjon. La oss se et eksempel.

(introduksjon / funksjon-modifikasjon.js)

i eksemplet ovenfor har vi opprettet en funksjon som overstyrer seg selv med en ny funksjonsimplementering. Dette ville være det hardeste eksempelet på modifikasjon, men vi har andre, kanskje mer meningsfulle brukssaker.

(introduksjon / readonly-objekt.js)

i eksemplet ovenfor har vi brukt Object.defineProperty() metode for å endre standard egenskapsbeskrivelse for name egenskapen for å gjøre den skrivebeskyttet. Du kan også brukeObject.freeze() – metoden for å låse hele objektet for å unngå mutasjoner.

noen forbønner kan skje gjennom modifikasjoner som du kan fra eksemplet ovenfor. Ved å sette writable:false i egenskapsbeskrivelsen til objektet, derfor muterer objektet (intern implementering), har vi startet verditildelingsoperasjonen.

hvis du ikke er kjent med valueOf – metoden, brukes den til å tvinge et objekt til en primitiv verdi. Så hvis jeg har et objekt og det har valueOf metode på seg selv eller på prototypekjeden, kalles Denne metoden Av JavaScript når du prøver å utføre en aritmetisk operasjon på den. Som standard harObjectvalueOf metoden som returnerer seg selv (objektet).

(introduksjon / verdiav.js)

som du kan se i eksemplet ovenfor, emp1/10 resulterte i en NaN siden et objekt ikke kan deles som naturlige tall. Men senere har vi lagt til valueOf metode på Employee klasse som returnerersalary verdien av objektet. Derforemp2/10 returnerte200 sidenemp2.salary er200. På samme måteemp3/10 returnerte300 som vi har lagtvalueOf metoden direkte påemp3.

Så i hvert trinn i eksemplet ovenfor griper vi inn i hvordan et objekt presenteres for en standard JavaScript-operasjon og endrer sin oppførsel til våre likings. Dette er ingenting annet enn forbønn.

I ES2015 (ES6) har JavaScript introdusert en ny primitiv datatype som ersymbol. Det er ingenting som vi har sett før og kan ikke representeres i bokstavelig form. Den kan bare bygges ved å ringeSymbol – funksjonen.

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

i et nøtteskall produserer det unike verdier som også kan brukes som vanlige objekttaster ved hjelp av obj notasjon der key ville være et symbol.

var key = Symbol();var obj = {
name: 'Ross',
: 200
};console.log( obj.name ); // 'Ross'
console.log( obj ); // 200
Object.keys(obj); // obj = 300;

siden de er unike, er det ingen måte å lage et duplikat symbol ved et uhell. Hvert nytt symbol er unikt (opprettet med Symbol()), noe som betyr at hvis du vil bruke et samme symbol, må du lagre det i en variabel og sende den variabelen rundt for å referere til det samme symbolet.

i eksempletvalueOf kan du se problemet hvis vi ikke er forsiktige eller oppmerksomme. Siden valueOf er en string eiendom (som i emp3 kan hvem som helst overstyre det ved et uhell , eller noen som ikke vet om valueOf kan planlegge å bruke den til eget bruk og tenke «hva ligger det i navnet?».Siden symboler også kan brukes som objektnøkler, Har JavaScript gitt noen globale symboler som skal brukes som objektnøkler for noen Standard JavaScript-operasjoner. Siden disse symbolene er velkjente for en utvikler, kalles de «kjente symboler». Disse kjente symbolene er utsatt for publikum som de statiske egenskapene tilSymbol funksjon.

Et av de kjente symbolene er Symbol.toPrimitive som skal brukes som nøkkelen til objektet for å oppnå sin primitive verdi. Ja, du tenker riktig, det er en erstatning for valueOf metode og det er foretrukket.

(introduksjon / symbol-toPrimitive.js)

💡toPrimitive metoden gjør mer enn bare å returnere en tallverdi av objektet. Vennligst les Symbolene leksjoner for å vite mer om det.

JavaScript gir mange slike kjente symboler for å fange opp og endre Standard JavaScript-oppførsel rundt objekter. Vi vil snakke om dette og symboler generelt i Symbolleksjonen.