Nájdenie cesty s .Map ()

Výrečnosť a elegancia riešenia sú riadené nástrojmi, ktoré musíme na vyriešenie konkrétneho problému. Aj keď cieľom riešenia problému je vyriešiť problém , jeho metódy by sa mali pohybovať čo najelegantnejším spôsobom. Zdá sa však, že cesta k takémuto riešeniu leží na asymptotickej krivke. Dokonalosť je stále bližšie a bližšie, ale navždy zostáva mimo dosahu.

Problém

Predstavte si, že máte pole a musíte zmeniť každý prvok v poli. Možno napríklad naberať množstvo výšok v palcoch a je potrebné ich prevádzať na centimetre. Alebo možno prevod poľa teplôt v Celcius na Fahrenheita. Ak ste v programovaní nováčikom, vaša myseľ by sa mohla okamžite dostať do nejakej formy slučky. A hádaj čo? Som si istý, že by ste to mohli zariadiť.

Avšak, ja som tu, aby vám ešte jeden nástroj - niečo, čo sa vám len trochu bližšie k elegantný: Array.prototype.map().

mapMetóda nám umožňuje transformovať každý prvok z poľa, bez toho by to ovplyvnilo pôvodnú poľa. Je to považované za funkciu vyššieho rádu a techniku ​​funkčného programovania, pretože to berie funkciu ako argument a my vykonávame výpočty bez mutácie stavu našej aplikácie.

Mapje vlastnosť, ktorá sa dedí z prototypu poľa. Prototypy poskytujú zabudované metódy, s ktorými sú objekty dodávané (polia sú špeciálnym typom objektov v očiach JavaScriptu). Aj keď mapje to možno trochu cudzie, tento prototyp sa nelíši od napríklad Array.lengthprototypu. Jedná sa jednoducho o metódy, ktoré sú zapracované do JavaScriptu. Prototypy polí možno pridávať a mutovať pomocou: Array.prototype.= ...

Na konci tejto lekcie zistíme, ako to mapfunguje, a napíšeme vlastnú metódu prototypu poľa.

Čo teda robí .map ()?

Povedzme, že máte množstvo teplôt v stupňoch Celzia, ktoré chcete previesť na Fahrenheita.

Existuje niekoľko spôsobov, ako vyriešiť tento problém. Jedným zo spôsobov môže byť napísanie forslučky na vytvorenie poľa Fahrenheitových teplôt z daných teplôt Celzia.

Pomocou forslučky môžeme napísať:

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 })();

Je potrebné poznamenať niekoľko vecí:

  1. Funguje to.
  2. Používame výraz IMFE (Immediately Invoked Function Expression), aby sme tiež nemuseli funkciu volať.
  3. Je trochu verbálny a nie veľmi elegantný.

Map umožňuje nám prevziať vyššie uvedený kód a prepracovať ho na nasledujúci kód:

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

Ako teda mapa funguje?

Mapvezme funkciu a použije túto funkciu na každý prvok v poli. mapS programom ES5 by sme mohli napísať o niečo podrobnejšie, aby sme to videli o niečo jasnejšie.

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

Keby naša mapová funkcia dokázala povedať, čo robí, povedala by:

"Pre každý prvok v poli to vynásobím (9/5) a potom pridám 32. Keď je to hotové, vrátim výsledok ako prvok v novom poli s názvom fahrenheitTemps."

Pozrime sa na bežnejší prípad použitia. Predpokladajme, že máme množstvo peopleobjektov. Každý objekt má namea agepár kľúč-hodnota-pair. Chceme vytvoriť premennú, ktorá bude obsahovať iba mená všetkých v poli. S našou formetódou slučky by sme mohli napísať:

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]; })();

S map:

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

Všimnite si, že tu nič netransformujeme, jednoducho vrátime pár kľúč - hodnota name.

forSlučky opäť fungujú. Je to však podrobné a musíme vytvoriť novú vlastnú funkciu vždy, keď chceme urobiť inú transformáciu. Zásadnou súčasťou programovania je písanie DRY kódu (Don't Repeat Yourself). Tieto funkcie vyššieho rádu, ako napríklad mapa, nám umožňujú zložitejšie programovanie v menšom počte riadkov kódu, ako by sme bez nich zvládli.

Znovuobjavenie kolesa:

Aby sme lepšie pochopili, čo sa deje pod kapotou, vytvoríme si vlastnú funkciu mapy, ktorú pripojíme k prototypu poľa.

Najskôr, aby sme pripojili prototypovú metódu k Array, napíšeme:

Array.prototype.

tak pre nás:

Array.prototype.myMap =

Aký však bude náš kód?

Logiku, ktorú potrebujeme, už máme zo forslučiek vyššie. Musíme to len trochu rafinovať. Refaktorujme poslednú funkciu, ktorú sme napísali getNames().

Pamätajte, že táto funkcia vzala osobu (inými slovami prvok nášho poľa), urobila vlastnú transformáciu na tento prvok (so forslučkou a logikou) a vrátila pole mien (alebo nové pole).

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]; })();

Najskôr si zmeňme názov našej funkcie. Nakoniec táto nová metóda nepredpokladá, že vie, na aké pole bude pôsobiť:

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]; })();

Po druhé, vytvárame vlastnú verziu servera .map(). Vieme, že to bude trvať na funkcii, ktorú používateľ poskytne. Zmeňme parameter, ktorý naša funkcia berie:

// 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]; })();

Nakoniec netušíme, na aké pole bude táto metóda pôsobiť. Nemôžeme sa teda odvolávať, people.lengthale môžeme sa odvolávať this.length. this, vráti pole, na ktoré metóda pracuje. Poďme si tiež vyčistiť niektoré z ďalších názvov premenných:

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; })();

Už sme skoro tam, ale na jednu vec zabúdame. Pole sme nepremenili! Všetko, čo sme urobili vyššie, je vrátiť staré pole. Užívateľom poskytovanú funkciu musíme aplikovať na každý prvok poľa:

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; })();

Na záver môžeme pripojiť našu novú funkciu Array.prototype.

Array.prototype.myMap = myMap;

Záverečná kontrola zdravotného stavu:

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

Zhrnutie

Mapje prototypová metóda, ktorú ponúkajú polia. V zákulisí iteruje cez pole a na každý prvok aplikuje funkciu poskytnutú používateľom. Nakoniec vráti nové pole s transformovanými hodnotami. Robí to bez mutácie pôvodného poľa. Pretože parameter, ktorý berie, je funkcia, považuje sa za funkciu vyššieho rádu. Jeho použitie navyše spadá do paradigmy funkčného programovania.

Vďaka za prečítanie!

woz