Методы .each() и .map()

Методы .each() и .map() в Umbrella JS обеспечивают обход коллекций элементов и выполнение пользовательского кода для каждого узла. Оба принимают функцию-колбэк, однако отличаются ожидаемым результатом: .each() применяется для побочных действий и возвращает исходную коллекцию, .map() формирует новую коллекцию на основе значений, которые возвращает колбэк.

Метод .each()

.each() перебирает текущую выборку элементов. Колбэк получает на вход сам элемент, индекс и набор аргументов, зависящий от ситуации. Возврат значения из колбэка игнорируется. Возвращаемым значением самого метода служит исходный объект u(...), что обеспечивает цепочку вызовов.

Ключевые особенности:

  • Используется для изменения свойств узлов, добавления классов, управления атрибутами.
  • Удобен для сценариев, где важен факт перебора, а не формирование нового набора данных.
  • Имеет семантику side-effect: любые действия внутри колбэка могут изменять DOM и состояние.

Пример изменения атрибутов

u('input').each(function(el, i){
  el.setAttribute('data-index', i);
});

В примере каждому input назначается атрибут data-index с соответствующим номером.

Пример взаимодействия с классами

u('.item').each(function(el){
  el.classList.add('active');
});

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

u('.item').each(...).addClass('processed');

Метод .map()

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

Ключевые особенности:

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

Извлечение атрибутов

const ids = u('.widget').map(function(el){
  return el.id;
});

Переменная ids содержит коллекцию со строками идентификаторов. В отличие от .each(), результатом здесь становится новый набор значений.

Фильтрация по условию

const visible = u('.panel').map(function(el){
  return el.offsetWidth > 0 && el.offsetHeight > 0 ? el : null;
});

Возврат null исключает элемент из результирующей выборки. Метод .map() обеспечивает лаконичную фильтрацию без дополнительных конструкций.

Трансформация структуры узлов

const labels = u('input[type="text"]').map(function(el){
  const label = document.createElement('label');
  label.textContent = el.name;
  return label;
});

В результате появляется коллекция из новых label, независимая от исходных input.

Сравнение поведения

Возврат значения: .each() игнорирует возвраты колбэка, .map() использует их для построения новой выборки. Цепочка вызовов: оба метода возвращают объект u(...), но .each() сохраняет исходную выборку, тогда как .map() формирует новую. Цель использования: .each() подходит для действий над DOM и побочных эффектов, .map() — для вычислений и преобразований.

Особые случаи

Umbrella допускает возврат массивов узлов в .map(), что дает возможность развернуть структуру в более широкий набор. Аналогично допустимо возвращать значения произвольного типа, включая строки и числа, что упрощает интеграцию с последующей логикой.

Работа обоих методов не прерывается досрочно. Для имитации остановки перебора применяется условная логика внутри колбэка. Differences по части производительности минимальны, поскольку операции выполняются по коллекции один раз без лишних проходов.

Практические паттерны

Выделение данных:

const names = u('.user').map(el => el.getAttribute('data-name'));

Модификация элементов с продолжением цепочки:

u('.btn').each(el => el.disabled = true).addClass('blocked');

Комбинация фильтрации и трансформации:

const links = u('a').map(function(el){
  return el.href.startsWith('https') ? el : null;
});

Формирование новых структур:

const items = u('.row').map(el => Array.from(el.children));

Здесь возвращается массив детей для каждой строки, затем Umbrella объединяет все элементы в единую плоскую коллекцию.

Взаимодействие с другими методами Umbrella

Результаты .map() могут передаваться в последующие вызовы для построения цепочек, приводящих к генерации динамических интерфейсов. .each() сочетается с методами управления атрибутами и классами, такими как .attr(), .addClass() и .removeClass(). Благодаря единой модели выбора узлов эти комбинации остаются предсказуемыми и компактными.

Колбэки в обоих методах работают в контексте обычных функций JavaScript, поддерживая стрелочные и традиционные формы записи. Отсутствие собственного контекста this в Umbrella снижает риск неоднозначности и упрощает чтение кода.

Детали реализации

Внутренний цикл Umbrella стремится минимизировать накладные расходы: перебор идет по статическому списку узлов, указанному при создании выборки. .map() аккумулирует результаты в массив, фильтруя недопустимые значения и исключая undefined и null. .each() использует ту же схему перебора, но игнорирует полученные значения.

Поддержка цепочек обеспечивается возвращением объекта u(...) на каждом шаге. Это позволяет согласованно комбинировать обход, фильтрацию и модификацию.

Рекомендации по использованию

.each() применим, когда необходим прямой доступ к DOM без изменения состава коллекции. .map() целесообразен при формировании новой выборки или данных. Четкое разделение ролей этих методов снижает сложность кода и облегчает чтение.