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 →