Перейти к содержимому

Js map что это

  • автор:

Метод map

Метод map позволяет применить заданную функцию для каждого элемента массива. При этом метод не изменяет исходный массив, а возвращает измененный.

Метод в параметре получает функцию, которая выполнится для каждого элемента массива. То, что вернет эта функция через return для элемента массива, станет новым значением этого элемента (см. примеры).

В функцию можно передавать 3 параметра. Если эти параметры есть (они не обязательны), то в первый автоматически попадет элемент массива, во второй попадет его номер в массиве (индекс), а в третий — сам массив.

Синтаксис

let новый массив = массив.map(function(элемент, индекс, массив) < код return измененный элемент; >);

Пример

Создадим массив, каждый элемент которого вдвое больше соответствующего элемента начального массива:

let arr = [1, 2, 3, 4, 5]; let res = arr.map(function(elem) < return elem * 2; >); console.log(res);

Результат выполнения кода:

[2, 4, 6, 8, 10]

Пример

Создадим массив, каждый элемент которого получается так — значение элемента умножается на его порядковый номер в массиве:

let arr = [1, 2, 3, 4, 5]; let res = arr.map(function(elem, index) < return elem * index; >); console.log(res);

Результат выполнения кода:

[0, 2, 6, 12, 20]

Пример

При необходимости в третий параметр можно передать сам массив:

let arr = [1, 2, 3, 4, 5]; let res = arr.map(function(elem, index, arr) < тут будет доступен массив arr >);

Смотрите также

  • метод forEach ,
    который применяет функцию для каждого элемента массива
  • метод filter ,
    который позволяет фильтровать элементы массива
  • методы some и every ,
    выполняющие проверку массива
  • методы reduce и reduceRight ,
    сворачивающие массив к одному значению

Source Maps: быстро и понятно

Механизм Source Maps используется для отображения исходных текстов программы на сгенерированные на их основе скрипты. Несмотря на то, что тема не нова и по ней уже написан ряд статей (например эта, эта и эта) некоторые аспекты все же нуждаются в прояснении. Представляемая статья представляет собой попытку упорядочить и систематизировать все, что известно по данной теме в краткой и доступной форме.

В статье Source Maps рассматриваются применительно к клиентской разработке в среде популярных браузеров (на примере, DevTools Google Chrome), хотя область их применения не привязана к какому-либо конкретному языку или среде. Главным источникам по Source Maps является, конечно, стандарт, хотя он до сих пор не принят (статус — proposal), но, тем не менее, широко поддерживается браузерами.

Работа над Source Maps была начата в конце нулевых, первая версия была создана для плагина Firebug Closure Inspector. Вторая версия вышла в 2010 и содержала изменения в части сокращения размера map-файла. Третья версия разработана в рамках сотрудничества Google и Mozilla и предложена в 2011 (последняя редакция в 2013).

В настоящее время в среде клиентской разработки сложилась ситуация, когда исходный код почти никогда не интегрируется на веб-страницу непосредственно, но проходит перед этим различные стадии обработки: минификацию, оптимизацию, конкатенацию, более того, сам исходный код может быть написан на языках требующих транспиляции. В таком случае, для целей отладки необходим механизм позволяющий наблюдать в дебаггере именно исходный, человекочитаемый код.

Для работы Source Maps необходимы следующие файлы:

  • собственно сгенерированный JavaScript-файл
  • набор файлов с исходным кодом использовавшийся для его создания
  • map-файл отображающий их друг на друга
Map-файл

Вся работа Source Maps основана на map-файле, который может выглядеть, например, так:

Обычно, имя map-файла складывается из имени скрипта, к которому он относится, с добавлением расширения «.map», bundle.js — bundle.js.map. Это обычный json-файл со следующими полями:

  • «version» — версия Source Maps;
  • «file» — (опционально) имя сгенерированного файла, к которому относится текущий map-файл;
  • «sourceRoot» — (опционально) префикс для путей к файлам-исходникам;
  • «sources» — список путей к файлам-исходникам (разрешаются аналогично адресам src тега script, можно использовать file://.);
  • «names» — список имен переменных и функций, которые подверглись изменению в сгенерированном файле;
  • «mappings» — координаты отображения переменных и функций исходных файлов на сгенерированный файл в формате Base64 VLQ;
  • «sourcesContent» — (опционально) в случае self-contained map-файла список строк, каждая из которых содержит исходный текст файла из sources;
Загрузка Source Maps

Для того, чтобы браузер загрузил map-файл может быть использован один из следующих способов:

  • JavaScript-файл пришел с HTTP-заголовком: SourceMap: (ранее использовался ныне устаревший X-SourceMap: )
  • в сгенерированном JavaScript-файле есть особый комментарий вида:
//# sourceMappingURL= (для CSS /*# sourceMappingURL= */) 

Таким образом, загрузив map-файл браузер подтянет и исходники из поля «sources» и с помощью данных в поле «mappings» отобразит их на сгенерированный скрипт. Во вкладке Sources DevTools можно будет найти оба варианта.

Для указания пути может использоваться пседопротокол file://. Также, в может быть включено все содержимое map-файла в кодировке Base64. В терминологии Webpack подобные Source Maps названы inline source maps.

//# sourceMappingURL=data:application/json;charset=utf-8;base64,

Ошибки загрузки Source Maps

Следует заметить, что map-файлы не являются частью веб-страницы, поэтому вы не увидите информации об их загрузке во вкладке Network DevTools. Тем не менее, если в сгенерированном файле находится ссылка на несуществующий map-файл, в Console DevTools будет предупреждение вида: «DevTools failed to load SourceMap: . ». Также при наличии ссылки на несуществующий исходник, вместо него будет сообщение вида: «Could not load content for . ».

Self-contained map-файлы

Код файлов-исходников можно включить непосредственно в map-файл в поле «sourcesContent», при наличии этого поля необходимость в их отдельной загрузке отпадает. В этом случае названия файлов в «sources» не отражают их реального адреса и могут быть совершенно произвольными. Именно поэтому, вы можете видеть во вкладке Sources DevTools такие странные «протоколы»: webpack://, ng:// и т.д

Mappings

Сущность механизма отображения состоит в том, что координаты (строка/столбец) имен переменных и функций в сгенерированном файле отображаются на координаты в соотвествующем файле исходного кода. Для работы механизма отображения необходима следующая информация:

(#1) номер строки в сгенерированном файле;
(#2) номер столбца в сгенерированном файле;
(#3) индекс исходника в «sources»;
(#4) номер строки исходника;
(#5) номер столбца исходника;

Все эти данные находятся в поле «mappings», значение которого — длинная строка с особой структурой и значениями закодированными в Base64 VLQ.

Строка разделена точками с запятой (;) на разделы, соответствующие строкам в сгенерированном файле (#1).

Каждый раздел разделен запятыми (,) на сегменты, каждый из которых может содержать 1,4 или 5 значений:

  • номер столбца в сгенерированном файле (#2);
  • индекс исходника в «sources» (#3);
  • номер строки исходника (#4);
  • номер столбца исходника (#5);
  • индекс имени переменной/функции из списка «names»;

Каждое значение представляет собой число в формате Base64 VLQ. VLQ (Variable-length quantity) представляет собой принцип кодирования сколь угодно большого числа с помощью произвольного числа двоичных блоков фиксированной длины.

В Source Maps используются шестибитные блоки, которые следуют в порядке от младшей части числа к старшей. Старший 6-й бит каждого блока (continuation bit) зарезервирован, если он установлен, то за текущим следует следующий блок относящийся к этому же числу, если сброшен — последовательность завершена.

Поскольку в Source Maps значение должно иметь знак, для него также зарезервирован младший 1-бит (sign bit), но только в первом блоке последовательности. Как и ожидается, установленный sign бит означает отрицательное число.

Таким образом, если число можно закодировать единственным блоком, оно не может быть по модулю больше 15 (11112), так как в первом шестибитном блоке последовательности два бита зарезервированы: continuation бит всегда будет сброшен, sign бит будет установлен в зависимости от знака числа.

Шестибитные блоки VLQ отображаются на кодировку Base64, где каждой шестибитной последовательности соответствует определенный символ ASCII.

Декодируем число mE. Инверсируем порядок, младшая часть последняя — Em. Декодируем числа из Base64: E — 000100, m — 100110. В первом отбрасываем старший continuation бит и два лидирующих нуля — 100. Во втором отбрасываем старший continuation и младший sign биты (sign бит сброшен — число положительное) — 0011. В итоге получаем 100 00112, что соответствует десятичному 67.

Можно и в обратную сторону, закодируем 41. Его двоичный код 1010012, разбиваем на два блока: старшая часть — 10, младшая часть (всегда 4-битная) — 1001. К старшей части добавляем старший continuation бит (сброшен) и три лидирующих нуля — 000010. К младшей части добавляем старший continuation бит (установлен) и младший sign бит (сброшен — число положительное) — 110010. Кодируем числа в Base64: 000010 — C, 110010 — y. Инверсируем порядок и, в итоге, получаем yC.

Для работы с VLQ весьма полезна одноименная библиотека.

Map и Set в JavaScript для удобной работы с данными

JavaScript предлагает несколько встроенных структур данных, которые облегчают работу с коллекциями. В этой статье мы рассмотрим два таких инструмента — Map и Set, их преимущества, особенности использования, а также примеры практического применения.

Отличие Map от Object

Map — это вид объекта JavaScript, но в отличии от обычных объектов, ключи в Map могут быть любым типом данных, а не только строками или символами. Однако важно понимать, что для корректной работы с этой структурой данных нужно использовать специальные методы и свойства:

  • new Map() – создаёт коллекцию принимая массив или другой итерируемый объект (const myMap = new Map([[1, “a”], [2, “b”]]).
  • .set(key, value) – записывает по ключу key значение value при этом возвращая ту же коллекцию, поэтому можно строить цепочки (myMap.set(1, «a»).set(2, «b»)).
  • .size – возвращает текущее количество пар ключ-значение. Это количество нельзя переопределить как length у массива.
  • .get(key) – возвращает значение по ключу или undefined, если ключ key отсутствует.
  • .delete(key) – удаляет пару ключ-значение по ключу key и возвращает true если ключ key был в коллекции, в противном случае прокидывает ошибку.
  • .clear() – полностью очищает коллекцию от всех пар ключ-значение .
  • .has(key) – проверяет наличие ключа key в коллекции и возвращает ответ в виде булева значения (true если ключ найден и false если нет).
  • .keys() – возвращает итерируемый объект по ключам.
  • .values() – возвращает итерируемый объект по значениям.
  • .entries() – возвращает итерируемый объект по парам вида [key, value], этот вариант используется по умолчанию в for..of.
  • .forEach — метод для перебора Map, схожий со встроенным методом массивов.

На примере выше мы видим, как при попытке присвоить обычному объекту ключи в виде других объектов, значение перезаписывается, а не создается новое свойство. Это происходит потому что объекты, которые мы передали как ключи, преобразуются в строку и строковое выражение обоих объектов john и kate равно друг другу(‘[object Object]’). При попытке добавить в Map пары ключ-значение через прямое обращение без метода set (map[key]=value) эти пары не добавляются. Все начинает работать как задумано только при использовании специальных методов. Такое ограничение синтаксиса может показаться неудобным, ведь если мы не знаем в каком формате (Map и Object) к нам приходят данные, придется писать проверку и работать с ними по разному, но, из-за такой чувствительности к применению методов, Map становится безопаснее, ведь нельзя переназначить свойства по-умолчанию (как length у массива) и изменить прототип коллекции.

Map (как и Set) использует алгоритм SameValueZero для сравнения ключей. Этот алгоритм практически идентичен оператору строгого сравнения (===), за исключением того, что NaN считается равным NaN. Поэтому, NaN может быть использован в качестве ключа в Map. Важно отметить, что этот алгоритм не может быть изменен или модифицирован.

В отличии от объектов, Map хранит пары ключ-значение в том порядке, в котором они были добавлены, что может быть полезно при переборе.

Есть у Map и серьезные недостатки. У этой структуры данных нет встроенной поддержки сериализации или синтаксического анализа. Т.е. мы не можем просто передать Map в JSON.stringify() что бы получить строку со всеми данными или распарсить JSON и получить полную структуру Map. Придется писать свою реализацию.

В примере выше мы преобразуем Map в простые пары ключ-значение с помощью метода entries и передаем результат в метод fromEnteries глобального объекта Object что бы потом с помощью JSON.stringify преобразовать данные в строку. Что бы распарсить JSON в Map мы проводим обратные операции. Если такие конструкции кажутся слишком громоздкими, представьте, если бы ключом был объект, ведь при попытке собрать Object из такой пары наш ключ превратится в строку ‘[object Object]’ .

Применение Map

Структура данных Map в JavaScript предоставляет множество возможностей и находит широкое применение в различных случаях. Вот лишь несколько примеров:

Частое применение Map — это сохранение связи между объектами и другими значениями. Например, если мы хотим хранить метаданные отдельно от самой сущности.

Если Вам нужно очень часто добавлять и удалять пары ключ-значение Map хорошо оптимизирован для подобных операций и справляется в несколько раз быстрее, чем Object.

Даже если в Вашем коде не создано ни одного Map, умение работать с этой структурой данных все равно может пригодиться. Map-подобные объекты используются в браузерных Web API таких как AudioParamMap, RTCStatsReport, EventCounts, KeyboardLayoutMap, MIDIInputMap и MIDIOutputMap. Такие объекты работают по принципу Map и используют те же методы, однако отличаются ограничениями на типы данных, которые могут быть использованы в качестве ключей.

Set это коллекция уникальных значений без индексов и ключей. Для простоты понимания можно представить что Set это Map, которых хранит только значения, а не пары ключ-значение. Даже методы Set “достались” от Map, но т.к. хранятся не пары, а только само значение любого типа данных, методы .values() и .keys() у этой структуры данных полностью аналогичны, а метод .get() отсутствует. Интересно, что при переборе Set с помощью метода .forEach() или цикла for…of… функции будут доступны три аргумента: value, valueAgain (буквально “значение еще раз”) и сама коллекция.

Для добавления нового элемента используется метод .add(value). Этот метод назван по-другому не только что бы не создавать путаницы с его названием и названием структуры данных, но и потому что работает совсем иначе. Если переданное значение уже есть в коллекции — метод не производит ни каких действий, что делает его максимально быстрым в сравнении с аналогами у других типов данных. Метод .has(value) так же производительнее, чем схожий .inclused() у массивов. При этом важно помнить, что ссылочные типы данных, так же как и в Map, следует передавать именно по ссылке.

Наиболее частое применение Set — создание коллекций уникальных данных из массивов. Так лаконичная строка кода с использованием Set заменит большую конструкцию с проверкой каждого элемента массива на уникальность и выполнит подобную операцию в разы быстрее.

Заключение:

Map и Set это удобные инструменты для работы с данными в JavaScript. Они делают код более производительным, лаконичным и легким для чтения. Надеюсь данная статья была полезна для понимания столь важной темы, а если Вы хотите изучить основы языка или детально погрузиться в устройство JavaScript я подготовил подробные курсы.

JavaScript с нуля — основы языка и практика для начинающих

— 16 часов коротких лекций по 10 — 15 минут

— 15 упражнений для закрепления на практике1

— 5 тестов для проверки знаний

— Рейтинг ⭐ 4.9 на основании отзывов

— 30-ти дневная гарантия возврата денег

JavaScript Advanced — продвинутые концепции языка и ООП

— 18 часов коротких лекций по 10 — 15 минут

— 30упражнений для закрепления на практике

— 14 тестов для проверки знаний

— Рейтинг ⭐ 4.9 на основании отзывов

— 30-ти дневная гарантия возврата денег

js map что это

.map() — это метод массивов, который создает новый массив, проходя по каждому элементу вызываемой функции и возвращая результат выполнения этой функции для каждого элемента:

const numbers = [1, 2, 3, undefined]; const doubledNumbers = numbers.map(function (num)  return num * 2; >); console.log(doubledNumbers); // [2, 4, 6, NaN] 

В этом примере метод .map() применяет функцию, которая умножает каждый элемент массива numbers на 2 и возвращает новый массив doubledNumbers с измененными значениями.

Обратите внимание, что последним элементов в массиве является undefined . Поэтому, в результате выполнения map функции и операции умножения, мы получили NaN в результируещем массиве.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *