Обхождане на масив с map() 1
Сподели урока
В предишния урок разгледах как работи метода forEach()
, който се използва за обхождане на масив. В този урок ще разгледам друг метод - map()
, който също се използва за обхождане на масив. Каква ли е разликата между тях?
Тъй като често ми се налага да използвам map()
, днес ще отделя няколко минути, за да си припомня как точно работи.
Синтаксис
Синтаксиса на map()
изглежда така:
arrayName.map(function(element, index, array) {
// „Тяло” на функцията
}, thisArg);
arrayName
е името на масива, който искам да обходя.
map()
преминава през всеки елемент от масива във възходящ ред като изпълнява callback
функция за всеки от тях. Тя приема три параметъра:
element
- настоящия елемент от масиваindex
- индекса, на който се намира настоящия елементarray
- масива, върху който прилагамеmap()
thisArg
е втори, незадължителен параметър, който определя стойността на this
в callback
функцията.
map()
е част от Array обекта в JavaScript.
Въпреки очевидната прилика с forEach()
, този метод работи по малко по-различен начин.
forEach()
обхожда даден масив като изпълнява callback
функция за всеки елемент от него. Това е всичко. Звучи като доста монотонна работа. Скука!
map()
, от друга страна, освен че обхожда масива, ни връща бонус - нов масив, който е резултат от изпълнението на callback
функцията за всеки елемент от първоначалния масив. Йей! :)
Звучи ми объркващо! Трябва да разгледам няколко прости примера, за да го разбера.
За да съпоставя работата на forEach()
и map()
, ще използвам същите два примера, които разгледах в урока за forEach()
.
Първи пример
Разполагам с масив от числа и искам да разбера на колко е равен квадрата на всяко едно от тях.
Използвайки map()
това би изглеждало така:
[4, 12, 27, 14].map(function(number) {
console.log(number + " на квадрат е " + number * number);
});
Хм, това определено ми дава правилен резултат, но къде е новият масив, който трябваше да получа?
Така погледнато, примерът по-горе не представя правилно работата на map()
. Наистина, кода се изпълнява без грешка, но самата идея за използване на map()
е различна.
Идеята е, че разполагам с определен масив и искам, базирайки се на него, да създам нов масив, който ще използвам по-късно в своя код.
Ако искам просто да обходя определен масив, без да връщам нищо от него, forEach()
би ми свършил чудесна работа.
Погледнато от този ъгъл, примера по-горе ще стане:
var numbers = [4, 12, 27, 14];
var squares = numbers.map(function(number) {
return (number + " на квадрат е " + number * number);
});
console.log(numbers);
console.log(squares);
Нещата започват да се изясняват.
numbers
е първоначалния масив. squares
е новия масив. Забелязвам също, че map()
не промени (мутира) елементите на обхождания масив. Това е важно!
Виждам и един доста съмнителен return
! Той ми е нужен, за да върна стойността, която искам да запазя в новия масив. Ако го пропусна, map()
, понеже е супер любезен метод, все пак ще ми върне нов масив, но всеки елемент от него ще има стойност undefined
.
Доказателство:
var numbers = [4, 12, 27, 14];
var squares = numbers.map(function(number) {
number + " на квадрат е " + number * number;
});
console.log(squares);
Втори пример
Да предположим, че получавам задачка да създам функция, която приема масив с обекти, извършва някаква „магия” и връща определена информация. Всеки обект представлява отделна книга, която има свойства като ISBN номер, заглавие, автор и цена. Резултатът, който трябва да върна от тази функция, е нов масив, който съдържа единствено заглавията на книгите.
Масива, с който трябва да работя, изглежда така:
var books = [
{isbn: 0596517742, title: "JavaScript: The Good Parts", author: "Douglas Crockford", price: 13.57},
{isbn: 1593275846, title: "Eloquent JavaScript: A Modern Introduction to Programming", author: "Marijn Haverbeke", price: 17.00},
{isbn: 0596806752, title: "JavaScript Patterns", author: "Stoyan Stefanov", price: 12.67}
];
Резултатът трябва да бъде следния:
["JavaScript: The Good Parts", "Eloquent JavaScript: A Modern Introduction to Programming", "JavaScript Patterns"];
Това условие ми звучи като идеален кандидат за map()
!
Ето моето решение:
// Същия масив, който представих по-горе.
// Тук го пропускам, за да направя кода по-кратък
var books = [...];
var titles = books.map(function(book) {
return book.title;
});
// Принтиране на резултата в конзолата
console.log(titles);
Сравнявайки този код с кода, който използвах в урока за forEach()
, забелязвам че тук съм значително по-ефективен, защото използвам по-малко код за постигане на същия резултат.
Кратко обяснение
В titles
запазвам новият масив, който се връща след извикване на map()
.
callback
функцията на map()
приема три аргумента. На мен ми е нужен само първия. Наименувам го book.
return book.title;
връща единствено стойността на свойството title
.
Чрез console.log(titles);
принтирам съдържанието на titles
в конзолата, за да проверя дали резутата наистина е този, който очаквам в действителност.
Това е така. :)
Заключение
В този урок разгледах работата на map()
. Двата примера показват само малка част от ситуациите, в които този метод може да бъде полезен. Препоръчвам ти да сравниш кода в примерите от този урок с примерите от урока за forEach()
, за да откриеш разликата между тези два метода. Линковете по-долу ще те отведат до още полезна информация.
На мен лично ми беше от полза да си припомня всичко това. Надявам се, че ти също научи нещо ново. Не спирай да се учиш!
Допълнителна информация
Снимка от Jackie Nell.
Поздравления, това е краят на този урок!
За награда получаваш вкусен мъфин.
Хареса ли ти урока? Сподели го със света :)
1
Много благодаря за страхотния урок!
Всичко е представено по начин разбираем за напълно начинаеща, каквато съм аз. Много благодаря! Надявам се да има още подобни уроци...моля..