Find vej med .Map ()

Løshedens elegance og elegance er drevet af de værktøjer, vi har til at løse et bestemt problem. Mens målet med problemløsning er at løse et problem , skal dets metoder gå mod den mest elegante måde. Rejsen mod en sådan løsning synes imidlertid at ligge på en asymptotisk kurve. Perfektion kommer tættere og tættere på, men forbliver for altid uden for rækkevidde.

Problemet

Forestil dig at have en matrix og have brug for at ændre hvert element i arrayet. Måske for eksempel at tage en række højder i inches og har brug for at konvertere dem til centimeter. Eller muligvis konvertere en række temperaturer i Celcius til Fahrenheit. Hvis du er ny med programmering, kan dit sind straks gå til en form for en sløjfe. Og gæt hvad? Jeg er sikker på, at du kunne få det til at fungere.

Men jeg er her for at give dig en mere værktøj - noget for at få dig bare lidt tættere på elegant: Array.prototype.map().

Den mapmetode giver os mulighed for at omdanne hvert element i et array, uden at det påvirker den oprindelige array. Det betragtes som en højere ordensfunktion og en funktionel programmeringsteknik, fordi det tager en funktion som et argument, og vi udfører beregning uden at mutere tilstanden for vores applikation.

Maper en egenskab, der nedarves fra array-prototypen. Prototyper giver indbyggede metoder, som objekter leveres med (arrays er specielle objekttyper i øjnene af JavaScript). Selvom det mapkan være lidt mere fremmed, er denne prototype ikke anderledes end for eksempel Array.lengthprototypen. Dette er simpelthen metoder, der bages i JavaScript. Array-prototyper kan tilføjes og muteres af: Array.prototype.= ...

Ved afslutningen af ​​denne lektion vil vi opdage, hvordan det mapfungerer, og skrive vores egen array prototype metode.

Så hvad gør .map ()?

Lad os sige, at du har en række temperaturer i Celsius, som du vil konvertere til Fahrenheit.

Der er en række måder at løse dette problem på. En måde kan være at skrive en forsløjfe for at oprette en række Fahrenheit-temperaturer fra de givne Celsius-temperaturer.

Med forløkken skriver vi måske:

const celciusTemps = [22, 36, 71, 54]; const getFahrenheitTemps = (function(temp) { const fahrenheitTemps = []; for (let i = 0; i < celciusTemps.length; i += 1) { temp = celciusTemps[i] * (9/5) + 32 fahrenheitTemps.push(temp); } console.log(fahrenheitTemps); [71.6, 96.8, 159.8, 129.2 })();

Et par ting at bemærke:

  1. Det virker.
  2. Vi bruger et øjeblikkeligt påkrævet funktionsudtryk (IIFE) for at undgå at skulle ringe til funktionen.
  3. Det er lidt detaljeret og ikke særlig elegant.

Map giver os mulighed for at tage ovenstående kode og omlægge den til følgende:

const fahrenheitTemps = celciusTemps.map(e => e * (9/5) + 32); console.log(fahrenheitTemps); // [71.6, 96.8, 159.8, 129.2]

Så hvordan fungerer kort?

Maptager en funktion og anvender denne funktion på hvert element i arrayet. Vi kunne skrive maplidt mere detaljeret med ES5 for at se dette lidt mere tydeligt.

const fahrenheitTemps = celciusTemps .map(function(elementOfArray) { return elementOfArray * (9/5) + 32; }); console.log(fahrenheitTemps); // [71.6, 96.8, 159.8, 129.2]

Hvis vores kortfunktion kunne sige, hvad den laver, ville den sige:

"For hvert element i arrayet multiplicerer jeg det med (9/5) og tilføjer derefter 32. Når det er gjort, returnerer jeg resultatet som et element i et nyt array kaldet fahrenheitTemps."

Lad os se på en mere almindelig brugssag. Lad os antage, at vi har en række peopleobjekter. Hvert objekt har et nameog agenøgleværdipar. Vi vil oprette en variabel, der kun er navnene på alle i matrixen. Med vores forloop-metode skriver vi måske:

const people = [ {name: Steve, age: 32}, {name: Mary, age: 28}, {name: Bill, age: 41}, ]; const getNames = (function(person) { const names = []; for (let i = 0; i < people.length; i += 1) { name = people[i].name; names.push(name); } console.log(names); // [Steve, Mary, Bill]; })();

Med map:

const names = people.map(e => e.name); console.log(names) // [Steve, Mary, Bill];

Bemærk her, at vi ikke transformerer noget, vi returnerer simpelthen nøgleværdiparet name.

Igen forfungerer sløjferne. Men det er ordentligt, og vi er nødt til at oprette en ny brugerdefineret funktion hver gang vi vil foretage en anden transformation. En hoveddel af programmeringen er at skrive TØRRE kode (gentag ikke dig selv). Disse funktioner af højere orden såsom kort giver os mulighed for at udføre mere kompleks programmering i færre kodelinjer, end vi kunne uden dem.

Genopfinde hjulet:

For bedre at forstå, hvad der sker under emhætten, laver vi vores egen kortfunktion, som vi vil knytte til array-prototypen.

For det første skal vi vedhæfte en prototype-metode til en matrix:

Array.prototype.

så for os:

Array.prototype.myMap =

Men hvad bliver vores kode?

Vi har allerede den logik, vi har brug for fra forsløjferne ovenfor. Alt, hvad vi skal gøre, er at omlægge det lidt. Lad os omformulere den sidste funktion, vi skrev getNames().

Remember, this function took a person (in other words an element of our array), did a custom transformation to that element (with the for loop and some logic), and returned an array of names (or a new array).

const getNames = (function(person) { const names = []; for (let i = 0; i < people.length; i += 1) { name = people[i].name; names.push(name); } console.log(names); // [Steve, Mary, Bill]; })();

First, let’s change the name of our function. After all, this new method doesn’t assume to know what kind of array it will be acting upon:

const myMap = (function(person) { //Changed name const names = []; for (let i = 0; i < people.length; i += 1) { name = people[i].name; names.push(name); } console.log(names); // [Steve, Mary, Bill]; })();

Second, we are creating our own version of .map(). We know this will take a function that the user provides. Let’s change the parameter our function takes:

// It is a bit verbose, but a very clear parameter name const myMap = (function(userProvidedFunction) { const names = []; for (let i = 0; i < people.length; i += 1) { name = people[i].name; names.push(name); } console.log(names); // [Steve, Mary, Bill]; })();

Finally, we have no idea what array this method will act on. So, we can’t refer to people.length but we can refer to this.length. this, will return the array the method is acting on. Also, let's clean up some of the other variable names:

const myMap = (function(userProvidedFunction) { // change variable name const newArr = []; // use "this.length" for (let i = 0; i < this.length; i += 1) { // use "this[i]", and change variable name const newElement = this[i]; // update the array we push into newArr.push(newElement); } // Return the newly created array return newArr; })();

Vi er næsten der, men der er én ting, vi glemmer. Vi har ikke transformeret arrayet! Alt, hvad vi har gjort ovenfor, er at returnere det gamle array. Vi er nødt til at anvende den bruger-leverede funktion til hvert element i arrayet:

const myMap = (function(userProvidedFunction) { const newArr = []; for (let i = 0; i < this.length; i += 1) { /* Transform the element by passing it into the * user-provided function */ const newElement = userProvidedFunction(this[i]); newArr.push(newElement); } return newArr; })();

Endelig kan vi knytte vores nye funktion til Array.prototype.

Array.prototype.myMap = myMap;

En sidste fornuftskontrol:

const myArray = [1, 2, 3]; // Multiply each element x 2 const myMappedArray = myArray.myMap(e => e * 2) console.log(myMappedArray) // [2, 4, 6];

Resumé

Maper en prototype metode, der tilbydes af arrays. Bag kulisserne gentager det sig gennem arrayet og anvender en bruger-tilvejebragt funktion til hvert element. I sidste ende returnerer det et nyt array med de transformerede værdier. Det gør dette uden at mutere det originale array. Fordi parameteren det tager er en funktion, betragtes den som en højere ordensfunktion. Derudover falder dets anvendelse i det funktionelle programmeringsparadigme.

Tak for læsningen!

woz