Открыть сервис

Underscore.js

Underscore.js — это библиотека JavaScript, предоставляющая набор утилитарных функций для работы с коллекциями, массивами, объектами и функциями. Она была создана для упрощения типичных операций обработки данных, которые не поддерживались встроенными методами языка на момент её появления. Underscore.js является одной из первых и наиболее влиятельных библиотек функционального программирования для JavaScript, оказав значительное влияние на развитие языка и появление аналогичных решений, таких как Lodash.

История

Библиотека была создана Джереми Ашкенасом (Jeremy Ashkenas) в 2009 году. Ашкенас также известен как автор фреймворка Backbone.js и языка CoffeeScript. Underscore.js изначально разрабатывалась как вспомогательная библиотека для Backbone.js, предоставляющая необходимые утилиты для работы с данными без расширения встроенных прототипов объектов JavaScript.

Первая версия была выпущена в октябре 2009 года. Библиотека быстро завоевала популярность благодаря своей простоте, небольшому размеру (около 5-6 КБ в сжатом виде) и отсутствию зависимостей. В 2012 году, после появления более производительной и функционально богатой библиотеки Lodash, созданной Джоном-Дэвидом Далтоном (John-David Dalton), популярность Underscore.js начала снижаться. Тем не менее, она остаётся широко используемой, особенно в проектах, где важна стабильность и минималистичность.

Основные возможности

Underscore.js предоставляет более 100 функций, разделённых на несколько категорий. Основные категории включают работу с коллекциями, массивами, объектами, функциями и утилиты.

Работа с коллекциями (коллбэки)

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

  • _.each(list, iteratee): Выполняет итератор для каждого элемента коллекции. Аналог Array.prototype.forEach.
  • _.map(list, iteratee): Создаёт новый массив, преобразуя каждый элемент коллекции с помощью итератора. Аналог Array.prototype.map.
  • _.filter(list, predicate): Возвращает массив элементов, для которых предикат (функция-условие) вернул true. Аналог Array.prototype.filter.
  • _.reject(list, predicate): Противоположность filter — возвращает массив элементов, для которых предикат вернул false.
  • _.reduce(list, iteratee, [memo]): Сводит коллекцию к одному значению, последовательно применяя итератор к каждому элементу и накопленному результату. Аналог Array.prototype.reduce.
  • _.find(list, predicate): Возвращает первый элемент, для которого предикат вернул true, или undefined, если такой элемент не найден.
  • _.every(list, predicate): Проверяет, удовлетворяют ли все элементы коллекции условию предиката. Возвращает true или false. Аналог Array.prototype.every.
  • _.some(list, predicate): Проверяет, удовлетворяет ли хотя бы один элемент коллекции условию предиката. Аналог Array.prototype.some.
  • _.contains(list, value): Проверяет, содержит ли коллекция указанное значение. Возвращает true или false.

Работа с массивами

Функции для работы с массивами, не зависящие от итераторов, а оперирующие самими массивами и их элементами.

  • _.first(array, [n]): Возвращает первый элемент массива или первые n элементов.
  • _.last(array, [n]): Возвращает последний элемент массива или последние n элементов.
  • _.initial(array, [n]): Возвращает все элементы массива, кроме последнего (или последних n).
  • _.rest(array, [n]): Возвращает все элементы массива, начиная с первого (или с индекса n). Аналог Array.prototype.slice.
  • _.compact(array): Возвращает массив, из которого удалены все ложные значения (false, null, 0, "", undefined, NaN).
  • _.flatten(array, [shallow]): «Разворачивает» вложенные массивы в один плоский массив. Если аргумент shallow равен true, разворачивание происходит только на один уровень.
  • **_.without(array, *values)**: Возвращает массив, из которого удалены указанные значения.
  • **_.union(*arrays)**: Возвращает массив, содержащий уникальные значения из всех переданных массивов (объединение).
  • **_.intersection(*arrays)**: Возвращает массив, содержащий значения, присутствующие во всех переданных массивах (пересечение).
  • **_.difference(array, *others)**: Возвращает массив, содержащий значения из первого массива, которые отсутствуют в остальных (разность).
  • _.uniq(array, [isSorted], [iteratee]): Возвращает массив без дубликатов. Может быть оптимизирован для отсортированных массивов.
  • **_.zip(*arrays)**: Объединяет несколько массивов в один массив кортежей (массивов), где каждый кортеж содержит элементы с одинаковыми индексами из исходных массивов.
  • _.object(list, [values]): Преобразует массив пар [ключ, значение] в объект. Если передан второй массив, он используется как значения, а первый — как ключи.
  • _.chunk(array, length): Разбивает массив на массивы заданной длины.

Работа с объектами

Функции для манипуляции свойствами объектов.

  • _.keys(object): Возвращает массив ключей объекта. Аналог Object.keys.
  • _.values(object): Возвращает массив значений объекта.
  • _.pairs(object): Возвращает массив пар [ключ, значение] для каждого свойства объекта.
  • _.invert(object): Создаёт объект, меняя местами ключи и значения исходного объекта.
  • **_.pick(object, *keys)**: Возвращает новый объект, содержащий только указанные свойства.
  • **_.omit(object, *keys)**: Возвращает новый объект, исключая указанные свойства.
  • **_.extend(destination, *sources)**: Копирует все свойства из исходных объектов в целевой объект. Аналог Object.assign.
  • **_.defaults(object, *defaults)**: Заполняет свойства объекта значениями по умолчанию, если они отсутствуют.
  • _.has(object, key): Проверяет, содержит ли объект указанное свойство (собственное, не унаследованное). Аналог object.hasOwnProperty(key).
  • _.isEqual(object, other): Выполняет глубокое сравнение двух объектов на равенство. Рекурсивно сравнивает все вложенные свойства.

Работа с функциями

Функции для управления выполнением других функций (функции высшего порядка).

  • **_.bind(function, object, *arguments)**: Привязывает контекст this функции к указанному объекту и, опционально, частично фиксирует аргументы. Аналог Function.prototype.bind.
  • **_.partial(function, *arguments)**: Частичное применение — фиксирует часть аргументов функции, возвращая новую функцию с меньшим числом аргументов.
  • _.memoize(function, [hashFunction]): Мемоизация — кэширует результаты вызова функции на основе её аргументов. При повторном вызове с теми же аргументами возвращает закэшированный результат.
  • **_.delay(function, wait, *arguments)**: Вызывает функцию через указанное количество миллисекунд. Аналог setTimeout.
  • _.debounce(function, wait, [immediate]): Создаёт функцию, которая будет выполнена не чаще одного раза за указанный интервал времени. Полезно для обработки событий, таких как ввод текста или изменение размера окна.
  • _.throttle(function, wait): Создаёт функцию, которая будет выполнена не чаще одного раза в указанный интервал времени. Отличается от debounce тем, что гарантирует выполнение не реже одного раза за интервал, а не только после последнего вызова.
  • _.once(function): Создаёт функцию, которая может быть выполнена только один раз. Последующие вызовы возвращают результат первого выполнения.
  • _.wrap(function, wrapper): Оборачивает функцию в другую функцию, передавая ей в качестве аргумента оригинальную функцию.

Утилиты

Общие вспомогательные функции.

  • _.identity(value): Возвращает переданное значение. Используется как итератор по умолчанию.
  • _.constant(value): Возвращает функцию, которая всегда возвращает указанное значение.
  • _.noop(): Возвращает undefined. Используется как функция-заглушка.
  • _.times(n, iteratee): Выполняет итератор n раз и возвращает массив результатов.
  • _.random(min, max): Возвращает случайное целое число в диапазоне от min до max включительно.
  • _.now(): Возвращает текущее время в миллисекундах с 1 января 1970 года. Аналог Date.now.
  • _.template(templateString, [settings]): Функция для компиляции шаблонов. Позволяет встраивать JavaScript-код в строки с помощью синтаксиса <%= %> (вывод значения), <%- %> (вывод с экранированием HTML) и <% %> (выполнение произвольного кода).

Сравнение с Lodash

Lodash, созданная в 2012 году, является форком Underscore.js и её наиболее популярным конкурентом. Ключевые различия:

  • Производительность: Lodash, как правило, быстрее, особенно при работе с большими массивами, благодаря оптимизациям и использованию нативных методов.
  • Функциональность: Lodash имеет более широкий набор функций, включая глубокое клонирование (_.cloneDeep), работу с цепочками вызовов (_.chain), и более гибкие версии существующих функций.
  • Размер: Lodash имеет модульную архитектуру, позволяющую импортировать только необходимые функции, что может уменьшить размер бандла. Underscore.js поставляется как единый монолитный файл.
  • Совместимость: Underscore.js более консервативна и стремится к стабильности API, в то время как Lodash более активно развивается и может вводить изменения, несовместимые с предыдущими версиями.
  • Стиль: Underscore.js использует единый объект _ для всех функций. Lodash также использует _, но предоставляет возможность импорта отдельных функций.

Влияние и значение

Underscore.js сыграла ключевую роль в популяризации функционального подхода к программированию на JavaScript. Она продемонстрировала, что сложные операции с данными могут быть выражены простыми, декларативными вызовами функций, без необходимости писать циклы и управлять состоянием вручную. Многие функции, которые были новшеством в Underscore.js, впоследствии были добавлены в стандартную библиотеку JavaScript (например, Array.prototype.forEach, Array.prototype.map, Array.prototype.filter, Object.keys). Библиотека также оказала влияние на дизайн API многих других библиотек и фреймворков, включая Backbone.js и React.

Источники

  • Официальная документация Underscore.js (underscorejs.org)
  • Репозиторий Underscore.js на GitHub
  • Статья «Underscore.js vs Lodash: A Comparison» на сайте LogRocket
  • Книга «JavaScript: The Good Parts» Дугласа Крокфорда

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →