du skriver JavaScript og pludselig indser med rædsel og frygt, at du har skrevet en enorm funktion. Det er sket for de bedste af os. Nu kommer den næsten ustoppelige trang til at adskille funktionen i mindre stykker.
store funktioner betyder mange ansvarsområder på et sted og muligvis kodelugt også, så det er en god ide i sig selv. Men du vil bryde funktionen op på en sådan måde, at den ikke mister sin betydning eller kontekst. For at gøre det skal du tænke metodekæde – også kaldet funktionskæde. Denne artikel vil forklare, hvad jeg mener med det.
forudsætninger
før vi kommer i gang, her er et par JavaScript-koncepter, som du allerede har brug for at være fortrolig med:
- pil funktioner
- Array metoder
- async funktioner
mest erfarne udviklere vil have en vis erfaring med Array
metoder, såsom kort, reducere, og filter. Du har sandsynligvis allerede stødt på noget som dette:
const food = ;// This type of usage is very commonfood .map(item => item.type) .reduce((result, fruit) => { result.push(fruit); return ; }, );// result:
Metodekædning sker, når du vil kalde flere funktioner ved hjælp af det samme objekt og dets reference. I ovenstående eksempel returnerer array-metoden map
en Array
, som har et formidabelt antal metoder.
da du returnerer en reference, der peger på en Array
, har du adgang til alle egenskaberne for Array
. Det er det samme princip, som du bruger til din egen metode kæde.
bedre forståelse af dette
jeg vil ikke dække alle nuancer af this
, men det er godt at forstå, hvorfor this
fungerer som det gør. Uanset hvor erfaren du er, kan nøgleordet dette være svært at forstå. Det er ofte grunden til, at tingene ikke fungerer, som du forventer, at de skal være.
her er kernen i det: this
vil altid pege på den nuværende scope
eller forekomst, hvorfra den hedder. Et eksempel:
const dog = { is: null, log: () => console.log(this.is), bark() { this.is = "woofing"; this.log(); return this; }, walk() { this.is = "walking"; this.log(); return this; }, eat() { this.is = "eating"; this.log(); return this; }};dog .bark() .eat() .walk();
når du skriver en funktion som denne (ingen ordspil beregnet), vil du måske kæde metoder, der er relateret til objektet. Objektet dog
har 3 metoder: walk
, bark
og eat
. Hver gang jeg kalder nogen af dens funktioner, skal en konsol vise repræsentationen af, hvad hunden laver på det nøjagtige tidspunkt.
men der er et problem med det. Hvis du kører det i bro.ser, vil du indse, at det ikke fungerer som forventet. Det skyldes, at pilfunktioner bruger leksikalsk scoping, hvor this
henviser til dets omgivende omfang – i dette tilfælde window
, ikke selve objektet.
for at løse det skal vi bruge et anonymt funktionsopkald til at repræsentere egenskaben log
:
// instead of this: log: () => console.log(this.is),// use this: log() { console.log(this.is); }
nu vil hundens this
rækkevidde være tilgængelig inde i funktionen.
brug af klasse
du kan opnå det samme resultat ved hjælp af klasser:
class Dog { is = null; log() { console.log(this.is); } bark() { this.is = "woofing"; this.log(); return this; } walk() { this.is = "walking"; this.log(); return this; } eat() { this.is = "eating"; this.log(); return this; }}const dog = new Dog();dog .bark() .eat() .walk();
brug af Prototype
hvis du skal bruge prototype, skal du gøre det på denne måde:
function Dog() {}Dog.prototype.is = null;Dog.prototype.log = function() { console.log(this.is);};Dog.prototype.bark = function() { this.is = "woofing"; this.log(); return this;};Dog.prototype.walk = function() { this.is = "walking"; this.log(); return this;};Dog.prototype.eat = function() { this.is = "eating"; this.log(); return this;};const dog = new Dog();dog .bark() .eat() .walk();
Hvad Med Async-Funktioner?
async
funktioner er syntetisk sukker til løfter og generatorer. Når du erklærer en async
funktion, ved du, at den vil returnere et løfte. På grund af det har du også adgang til alle metoderne i løftet.
const requests = { user: null, action: null, log(something) { console.log(this); }, async getUser() { this.user = await new Promise(resolve => { setTimeout(() => { resolve("Douglas Pires"); }, 1000); }); this.log("user"); return this; }, async registerAction() { this.action = await new Promise(resolve => { setTimeout(() => { resolve("programming stuff"); }, 1000); }); this.log("action"); return this; }};requests.getUser().then(() => requests.registerAction());
det er dog ikke en god ide at kæde en masse løfter sammen. Jeg anbefaler at bruge en flok await
søgeord i stedet. Det er nemmere, og det vil gøre din kode meget mere læsbar.
await requests.getUser(); // Douglas Piresawait requests.registerAction(); // programming
og du har adgang til de samme ejendomme her:
console.log(requests.user); // Douglas Piresconsole.log(requests.action); // programming
afslutningsvis
Kædefunktioner er nyttige, når du skal manipulere et objekt. Det er også en praktisk måde at forbedre læsbarheden af din kode. Men som du har set ovenfor, bør du kæde klogt.
i denne artikel har vi talt om this
, klasser, prototyper og async
funktioner i forbindelse med JavaScript-metodekæde. Jeg håber du har hentet nogle nyttige tips og er nu bedre informeret om emnet. Du kan finde min repository med al kode på JavaScript metode kæde lige her. Vi ses i næste post!
nød at læse denne artikel? Du er velkommen til at dele på sociale medier ved hjælp af knapperne nedenfor. Alternativt har jeg også skrevet om, hvordan du kan opbygge en farvepaletgenerator ved hjælp af nust og Vuetify. Gå tjek det ud!