Проналажење пута са .Мап ()

Говорност и елеганција решења покрећу се алатима којима морамо решити одређени проблем. Иако је циљ решавања проблема решавање проблема , његове методе би требало да се крећу ка најелегантнијем могућем начину. Чини се да пут ка таквом решењу лежи на асимптотској кривој. Савршенство се приближава и приближава, али заувек остаје ван досега.

Проблем

Замислите да имате низ и да морате да промените сваки елемент у низу. Можда, на пример, узимање низа висина у инчима и њихово претварање у центиметре. Или претварање низа температура у Целзијусу у Фахренхеит. Ако сте нови у програмирању, ваш ум би могао одмах прећи на неки облик петље. И погодите шта? Сигуран сам да бисте могли да успете.

Међутим, ја сам овде да вам дам још један алат - нешто што ти само мало ближе елегантан: Array.prototype.map().

mapМетод нам омогућава да се трансформише сваки елемент низа, без утицаја на оригинални низ. Сматра се функцијом вишег реда и техником функционалног програмирања, јер узима функцију као аргумент, а ми вршимо рачунање без мутирања стања наше апликације.

Mapје својство које се наслеђује из прототипа низа. Прототипови пружају уграђене методе са којима долазе објекти (низови су посебне врсте објеката у очима ЈаваСцрипт-а). Иако је mapможда мало странији, овај прототип се не разликује од, на пример, Array.lengthпрототипа. То су једноставно методе које се уклапају у ЈаваСцрипт. Прототипи низа могу се додати и мутирати помоћу: Array.prototype.= ...

На крају ове лекције открићемо како mapфункционише и написаћемо сопствени метод прототипа низа.

Па, шта ради .мап ()?

Рецимо да имате низ температура у Целзијусу које желите да претворите у Фахренхеит.

Постоји више начина за решавање овог проблема. Један од начина може бити писање forпетље за стварање низа Фахренхеит-ових температура од задатих Целзијусових температура.

Помоћу forпетље можемо написати:

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

Неколико ствари које треба напоменути:

  1. Функционише.
  2. Користимо израз са непосредним позивом функције (ИИФЕ) како бисмо избегли да функцију такође морамо позвати.
  3. Помало је детаљан и не баш елегантан.

Map омогућава нам да узмемо горњи код и преправимо га на следеће:

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

Па како функционише мапа?

Mapузима функцију и примењује ту функцију на сваки елемент у низу. Могли бисмо да пишемо mapмало детаљније са ЕС5 да бисмо ово видели мало јасније.

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

Када би наша функција мапе могла рећи шта ради, рекла би:

„За сваки елемент у низу помножим са (9/5), а затим додам 32. Када је то завршено, вратим резултат као елемент у новом низу који се назива фахренхеитТемпс.“

Погледајмо чешћи случај употребе. Претпоставимо да имамо низ peopleобјеката. Сваки објекат има nameи ageкључ-вредност-пар. Желимо да креирамо променљиву која представља само имена свих у низу. Помоћу наше forметоде петље могли бисмо написати:

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

Са map:

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

Овде приметите да ништа не трансформишемо, ми једноставно враћамо пар кључ-вредност name.

Опет, forпетље раде. Али, то је опширно и морамо створити нову прилагођену функцију сваки пут када желимо да извршимо другачију трансформацију. Главни део програмирања је писање СУВОГ кода (Не понављајте се). Ове функције вишег реда попут мапе омогућавају нам сложеније програмирање у мање редова кода него што бисмо могли без њих.

Поновно проналазак точка:

Да бисмо боље разумели шта се догађа испод хаубе, направићемо сопствену функцију мапе коју ћемо приложити прототипу низа.

Прво, да бисмо Арраи-у придружили прототипну методу, написаћемо:

Array.prototype.

па за нас:

Array.prototype.myMap =

Али, шта ће бити наш код?

Већ имамо forгорњу логику која нам је потребна . Све што треба да урадимо је да то мало преправимо. Рефакторизирамо последњу функцију коју смо написали getNames().

Запамтите, ова функција је узела особу (другим речима, елемент нашег низа), извршила прилагођену трансформацију у тај елемент (са forпетљом и неком логиком) и вратила низ имена (или нови низ).

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

Прво, променимо назив наше функције. Напокон, овај нови метод не претпоставља да зна на какав ће низ деловати:

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

Друго, креирамо сопствену верзију .map(). Знамо да ће ово узети функцију коју корисник пружа. Променимо параметар који узима наша функција:

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

Коначно, немамо представу на који низ ће ова метода деловати. Дакле, не можемо се позивати, people.lengthали можемо се позивати this.length. this, вратиће низ на који метода делује. Такође, почистимо нека друга имена променљивих:

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

Скоро смо стигли, али једну ствар заборављамо. Нисмо трансформисали низ! Све што смо горе урадили је да вратимо стари низ. Морамо применити корисничку функцију на сваки елемент низа:

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

Коначно, можемо да приложимо нашу нову функцију Array.prototype.

Array.prototype.myMap = myMap;

Коначна провера здравственог стања:

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

Резиме

Mapје прототипска метода коју нуде низови. Иза кулиса се превлачи кроз низ, примењујући на сваки елемент функцију коју даје корисник. На крају, враћа нови низ са трансформисаним вредностима. То чини без мутирања оригиналног низа. Будући да је параметар који узима функција, сматра се функцијом вишег реда. Поред тога, његова употреба спада у парадигму функционалног програмирања.

Хвала за читање!

воз