Underscore.js - это библиотека JavaScript, которая предоставляет служебные функции для общих задач программирования. [2] Он сравним с функциями, предоставляемыми Prototype.js и языком Ruby , но в нем используется дизайн функционального программирования вместо расширения прототипов объектов . В документации Underscore.js называется «связующим звеном со смокингом jQuery и подтяжками Backbone.js ». Underscore.js был создан Джереми Ашкенасом , который также известен своими Backbone.js и CoffeeScript . [3]
Разработчики) | Джереми Ашкенас , Джулиан Гонгриджп |
---|---|
Первый выпуск | 28 октября 2009 г . [1] |
Стабильный выпуск | 1.13.1 / 15 апреля 2021 г . |
Репозиторий | |
Написано в | JavaScript |
Размер | 7,5 КБ производство 68 КБ разработка |
Тип | Библиотека JavaScript |
Лицензия | Массачусетский технологический институт |
Веб-сайт | underscorejs |
История
Джереми Ашкенас создал Underscore к концу 2009 года в качестве побочного продукта проекта DocumentCloud вместе с Backbone.js . Это была одна из первых библиотек для JavaScript, предоставляющих общие утилиты функционального программирования, вдохновленные Prototype.js , функциональным JavaScript Оливера Стила и Micro-Templating Джона Ресига. [4]
В 2012 году Джон-Дэвид Далтон создал форк Underscore под названием Lo-Dash (ныне Lodash ). Первоначально Lo-Dash позиционировался как альтернатива Underscore с «согласованностью, настройкой, производительностью и дополнительными функциями». [5] Тем не менее, Lodash уже на ранней стадии отошел от первоначального интерфейса Underscore [6] и начал вносить более радикальные изменения с выпуском 3.0.0, заставляя пользователей Lodash изменять свой код. [7]
В мае 2015 года Джереми Ашкенас объявил, что Джон-Дэвид Далтон связался с ним по поводу объединения библиотек. Несмотря на опасения по поводу стиля и размера кода, Ашкенас не возражал против объединения некоторых расширений Lodash в Underscore. [8] В то время несколько разработчиков работали над Underscore и Lodash параллельно; эта группа участников начала вносить изменения в Underscore, чтобы сделать его более похожим на Lodash. [9]
Однако параллельно с этим Далтон внес более радикальные изменения в интерфейс Lodash. В июне 2015 года он анонсировал Lodash версии 4.0.0, которая еще больше отдаляла Lodash от интерфейса Underscore, в то же время существенно отличаясь от самой серии Lodash версии 3.x. [10] [11] Это побудило некоторые проекты, которые зависели от Lodash, создать свои собственные дистрибутивы Lodash 3. [12]
В феврале 2016 года Далтон объявил, что считает операцию по слиянию завершенной. Он предложил пользователям перейти с Underscore на Lodash, мотивируя это статистикой доли использования. [13] Сопровождающий Underscore, однако, дал понять, что не собирался прекращать разработку Underscore как отдельной библиотеки. [14] Обе библиотеки вошли в состояние низкой активности разработки после 2016 года. [15] [16]
Со временем более новые версии стандарта ECMAScript добавили в язык встроенные функции, которые воспроизводят некоторые функции Underscore, такие как Object.assign
и Array.prototype.map
. Это может привести к мнению, что Underscore больше не добавляет ценности проекту JavaScript, хотя встроенные функции, однако, менее эффективны, чем их эквиваленты Underscore; в частности, встроенные методы массива итераций , таких как map
, filter
и forEach
не перебирать простые объекты и не поддерживают iteratee Shorthands . [17] [18] [19] [20] [21] [22] Кроме того, большинство функций Underscore до сих пор не имеют встроенного аналога. [23] [24]
По состоянию на март 2021 года Underscore активно разрабатывается Джулианом Гонгриджпом, который начал вносить значительный вклад в марте 2020 года. [15] Библиотека по-прежнему широко используется и загружается с npm несколько миллионов раз каждую неделю. [25]
Содержание
По сути, Underscore предоставляет три вещи:
- Коллекция из более чем 100 многоразовых функций, предназначенных для практического использования в повседневных приложениях. В документации различают несколько категорий:
- Функции сбора , такие как
find
,map
,min
/max
,groupBy
иshuffle
коллекции процесса данных. Эти функции могут работать с элементами массивов последовательностей, а также со свойствами объектов. - Массивы функции , такие как
first
/last
,flatten
,chunk
иzip
работают исключительно на массиве подобные объекты. - Функциональные функции , такие как
bind
,memoize
,partial
иdebounce
принимать функцию в качестве аргумента и возвращает новую функцию с измененными свойствами ( функции высшего порядка ). - Объектные функции - это более фундаментальная категория, содержащая множество функций, которые также повторно используются внутри Underscore. [26] Его можно условно разделить на две подкатегории:
- Функции тестирования типов, такие как
isNumber
,isElement
иisDataView
. - Функции , такие как
keys
,extend
,pick
/omit
,pairs
иinvert
, которые манипулируют (простой) объекты в качестве данных.
- Функции тестирования типов, такие как
- Вспомогательные функции - это категория отдыха. Среди прочего, он включает в себя тривиальные функции
identity
и функцииnoop
управления строкамиescape
,unescape
иtemplate
. В эту категорию также входят функцииiteratee
иmixin
, которые могут считаться специальными объектами, как в пункте 2.
- Функции сбора , такие как
- Специальные средства, такие как
chain
иiteratee
, которые сочетаются с функциями пункта 1, чтобы сделать синтаксис более коротким и понятным. Специальная функция_
, в честь которой названа библиотека, является центральной для этих возможностей. - Грамотный исходный код, предназначенный для чтения, чтобы легко было понять, как реализована библиотека. Документация включает отрисованную версию исходного кода, где комментарии находятся слева, а логика - справа. Комментарии отформатированы с использованием Markdown, а логика имеет подсветку синтаксиса . Начиная с версии 1.11, Underscore является модульным . По этой причине документация теперь включает как модульную версию аннотированного источника, в которой каждая функция находится на отдельной странице, а
import
ссылки представляют собой интерактивные гиперссылки , так и единую версию для чтения , где все функции находятся на одной странице в порядке зависимость .
Обзор и примеры функций
Подчеркивание продвигает функциональный стиль , в котором несколько функций могут быть объединены в одном выражении для получения новых функциональных возможностей. Например, в следующем выражении используются две функции подчеркивания для группировки слов по их первым символам:
импортировать { groupBy , first } из символа подчеркивания ;groupBy ([ 'авокадо' , 'абрикос' , 'вишня' , 'финик' , 'дуриан' ], первый );// результат:// {a: ['авокадо', 'абрикос'],// c: ['вишня'],// д: ['дата', 'дуриан']//}
Функции подчеркивания никоим образом не выделяются отдельно от пользовательских функций. Если бы пользователь реализовал свою собственную first
функцию, приведенное выше выражение работало бы одинаково хорошо:
импортировать { groupBy } из символа подчеркивания ;const first = array => array [ 0 ];groupBy ([ 'авокадо' , 'абрикос' , 'вишня' , 'финик' , 'дуриан' ], первый );
Однако набор функций, предоставляемых Underscore, специально выбран для минимизации таких усилий, чтобы пользователь мог составлять функциональность из существующих функций, а не писать свои собственные.
Функции, выполняющие итерацию по содержимому массива или объекта, обычно принимают данные в качестве первого параметра, а функцию итерации или итерацию - в качестве второго параметра. В приведенном выше first
примере передается итерация groupBy
.
Хотя итератору не требуется их использовать, в большинстве случаев он получает три аргумента: (1) значение в текущей позиции в коллекции, (2) ключ или индекс этого значения и (3) всю коллекцию. В следующем примере второй аргумент используется в итерации pick
, чтобы выбрать только свойства объекта, ключ которого начинается с заглавной буквы:
импортировать { выбрать } из подчеркивания ;const details = { Официальный : 'Вольфганг Амадей Моцарт' , неофициальный : 'Wolfie'};const keyIsUpper = ( значение , ключ ) => ключ [ 0 ] === ключ [ 0 ]. toUpperCase ();pick ( подробности , keyIsUpper );// {Официальный: 'Вольфганг Амадей Моцарт'}
Многие функции Underscore можно использовать в качестве итераций, как ранее было проиллюстрировано с помощью first
. Кроме того, есть несколько распространенных случаев, когда пользователь может избежать написания функции итерации, используя вместо нее сокращенную запись итерации . В следующем примере строка 'name'
используется как сокращенное обозначение итераций для извлечения всех name
свойств из массива объектов:
импортировать { карту } из подчеркивания ;const people = [ { имя : 'Лили' , возраст : 44 , профессия : 'библиотекарь' }, { имя : 'Гарольд' , возраст : 10 , профессия : 'мечтатель' }, { имя : 'Саша' , возраст : 68 , профессия : 'разработчик библиотеки' }];карта ( люди , 'имя' ); // ['Лили', 'Гарольд', 'Саша']
Все функции в категории «коллекции», в том числе groupBy
и map
функции продемонстрированной выше, можно перебирать и по индексам массива и ключей от объекта. Это проиллюстрировано ниже reduce
:
импортировать { уменьшить } из подчеркивания ;const add = ( a , b ) => a + b ;const sum = числа => уменьшить ( числа , добавить , 0 );сумма ([ 11 , 12 , 13 ]); // 36сумма ({ Алиса : 9 , Боб : 9 , Клэр : 7 }); // 25
Помимо функций, которые перебирают массивы или объекты, Underscore предоставляет широкий спектр других функций многократного использования. Например, throttle
ограничивает частоту, с которой оценивается функция:
импортировать { дроссель } из подчеркивания ;// Событие прокрутки срабатывает очень часто, поэтому следующая строка может// замедляем браузер.документ . тело . addEventListener ( 'свитка' , expensiveUpdateFunction );// Ограничение оценки до одного раза в 100 миллисекунд.const throttledUpdateFunction = throttle ( strictUpdateFunction , 100 );// Намного более плавный пользовательский интерфейс!документ . тело . addEventListener ( 'прокрутка' , throttledUpdateFunction );
Другой пример: defaults
присваивает свойства объекта, только если они еще не установлены:
импортировать { значения по умолчанию } из подчеркивания ;const requestData = { url : 'wikipedia.org' , метод : 'POST' , body : 'текст статьи'};const defaultFields = { метод : 'GET' , заголовки : { 'X-Requested-With' : 'XMLHttpRequest' }};значения по умолчанию ( requestData , defaultFields );// {// url: 'wikipedia.org',// метод: 'POST',// body: 'текст статьи',// заголовки: {'X-Requested-With': 'XMLHttpRequest'}//}
_
функция
Underscore получил свое название от функции _
, которая служит нескольким целям.
Функция обертки
В качестве функции _
возвращает упакованную версию любого значения, переданного в качестве первого аргумента. Этот специальный объект имеет все функции Underscore как методы, что позволяет использовать другую нотацию, называемую «стилем ООП»:
import _ , { последний } из символа подчеркивания ;// «Нормальный» или «функциональный» стильпоследний ([ 1 , 2 , 3 ]); // 3// "стиль ООП"_ ([ 1 , 2 , 3 ]). last () // 3
Эта функция используется в цепочке ( следующий раздел ). Значение можно снова развернуть с помощью .value()
метода для дальнейшей обработки вне Underscore. В некоторых случаях значения также разворачиваются автоматически.
// Явное развертывание_ ([ 1 , 2 , 3 ]). value () // [1, 2, 3]// Автоматическое разворачивание при принуждении к номеру1 + _ ( 2 ) // 3// Автоматическое разворачивание при принуждении к строке'abc' + _ ( 'def' ) // 'abcdef'// Автоматическое разворачивание при форматировании как JSONJSON . stringify ({ a : _ ([ 1 , 2 ]) }) // '{"a": [1,2]}'
Частичный заполнитель приложения
_
также действует как заполнитель для partial
функции. partial
создает частично примененную версию функции и _
может использоваться, чтобы оставить некоторые параметры «открытыми», чтобы их можно было предоставить позже. Например, groupBy
пример из обзора может быть расширен следующим образом, чтобы превратить выражение в функцию многократного использования:
import _ , { partial , groupBy , first } из символа подчеркивания ;const groupByFirstChar = partial ( groupBy , _ , первый );groupByFirstChar ([ 'авокадо' , 'абрикос' , 'вишня' , 'финик' , 'дуриан' ]);// {a: ['авокадо', 'абрикос'],// c: ['вишня'],// д: ['дата', 'дуриан']//}groupByFirstChar ([ 'каштан' , 'фисташка' , 'орех' , 'кешью' ]);// {c: ['каштан', 'кешью'],// p: ['фисташковый'],// w: ['орех]//}
Пункт настройки
Кроме того, он _
служит центральной точкой настройки, где пользователи могут настраивать поведение функций Underscore в соответствии со своими потребностями. В частности, пользователи могут переопределить _.iteratee
для создания новых сокращений итераций и _.templateSettings
для настройки template
функции.
Дескриптор пространства имен
В более общем смысле, все функции Underscore представлены как свойства _
, например, также _.map
и _.debounce
. Это позволяет использовать _
в качестве дескриптора пространства имен . С появлением модулей в ES6 наличие такого дескриптора пространства имен больше не является строго необходимым, но практика по-прежнему часто встречается в коде, использующем более старые модульные системы, такие как AMD и CommonJS :
var _ = require ( 'подчеркивание' );_ . groupBy ([ 'авокадо' , 'абрикос' , 'вишня' , 'финик' , 'дуриан' ], _ . сначала );
Учитывая существующую практику, это также может быть удобная нотация, чтобы уточнить, что одна означает функцию конкретно из библиотеки Underscore, а не функцию с тем же именем из другой библиотеки. Например, и Underscore, и Async предоставляют функцию с именем each
; чтобы различать их, можно написать _.each
и async.each
соответственно.
Цепочка
Функция chain
может быть использована для создания модифицированной версии обертки производимой в _функции . При вызове такой связанной оболочки каждый метод возвращает новую оболочку, чтобы пользователь мог продолжить обработку промежуточных результатов с помощью функций Underscore:
импортировать { цепочку } из символа подчеркивания ;const квадрат = х => х * х ;const isOdd = x => x % 2 ;цепочка ([ 1 , 2 , 3 , 4 ]). фильтр ( isOdd ). карта ( квадрат ). последний ()// возвращает обертку 9
Нередко функция, реализованная с помощью Underscore, полностью состоит из return
оператора с цепочкой, оканчивающейся на .value()
:
const add = ( x , y ) => x + y ;// Учитывая массив чисел, возвращаем сумму квадратов// эти числа. Это может быть использовано в библиотеке статистики.функция sumOfSquares ( числа ) { возвратная цепочка ( числа ) . карта ( квадрат ) . уменьшить ( добавить ) . значение ();}
Цепочка не является эксклюзивной для функций, поставляемых с Underscore. Пользователи также могут включить цепочку для своих собственных функций, передав их mixin
функции:
import { reduce , mixin } из символа подчеркивания ;const sum = числа => уменьшить ( числа , добавить , 0 );миксин ({ сумма , квадрат });цепочка ([ 1 , 2 , 3 ]). карта ( квадрат ). сумма (). значение (); // 14цепочка ([ 1 , 2 , 3 ]). сумма (). квадрат (). значение (); // 36
Фактически, именно так включается цепочка и для собственных функций Underscore. Все функции Underscore пишутся как обычные автономные функции, без какой-либо специальной подготовки к связыванию, а затем «подмешиваются» в _
функцию впоследствии. [27]
Итерационные сокращения
Как упоминалось ранее в обзоре , большинство функций Underscore, которые выполняют итерацию по массивам или объектам, принимают сокращенную запись как итерацию вместо функции. Повторяя пример из этого раздела здесь:
импортировать { карту } из подчеркивания ;const people = [ { имя : 'Лили' , подробности : { возраст : 44 , род занятий : 'пожарный' }}, { имя : 'Гарольд' , подробности : { возраст : 10 , род занятий : 'мечтатель' }}, { имя : 'Саша' , подробности : { возраст : 68 , профессия : 'разработчик библиотеки' }}];карта ( люди , 'имя' ); // ['Лили', 'Гарольд', 'Саша']
Под капотом эта нотация включается путем передачи сокращенного значения _.iteratee
для получения функции. _.iteratee
по умолчанию используется iteratee
функция, поставляемая с Underscore, которая, в зависимости от значения, возвращает функцию следующим образом.
Пути
Если значение является строкой, iteratee
пересылает значение в property
, который интерпретирует строку как ключ свойства. Он возвращает функцию, которая пытается извлечь свойство с заданным ключом из своего аргумента. Все следующие выражения эквивалентны:
import { iteratee , property } из символа подчеркивания ;карта ( люди , 'имя' );карта ( люди , итерация ( 'имя' ));карта ( люди , собственность ( 'имя' ));карта ( люди , obj => obj && obj [ 'name' ]);// ['Лили', 'Гарольд', 'Саша']
Также передаются массивы и числа property
. Массивы можно использовать для получения вложенных свойств:
карта ( люди , [ 'подробности' , 'род занятий' ]);// ['пожарный', 'мечтатель', 'разработчик библиотеки']
Числа могут использоваться как индексы массива и строки. Объединив все это, мы можем использовать следующее выражение, чтобы подсчитать, сколько раз буквы алфавита встречаются как второй символ профессии человека:
импортировать { countBy } из символа подчеркивания ;countBy ( люди , [ 'подробности' , 'занятие' , 1 ]); // {i: 2, r: 1}
Хэши атрибутов
Когда значение является объектом, iteratee
пересылает его в matcher
, который интерпретирует объект как набор атрибутов, которые должны быть сопоставлены. Он возвращает функцию, которая будет возвращать, true
или в false
зависимости от того, имеет ли ее аргумент тот же набор атрибутов.
импортировать { найти } из подчеркивания ;найти ( люди , { имя : 'Саша' });// {имя: 'Саша', реквизиты: {возраст: 68, профессия: 'разработчик библиотеки'}}найти ( люди , { имя : 'Уолтер' });// неопределенный
null
а также undefined
Если значение равно null
или undefined
, iteratee
возвращает функцию идентификации, которую Underscore экспортирует как identity
. Это можно использовать для фильтрации истинных значений из коллекции:
import { filter , iteratee , identity } из 'подчеркивания' ;const example = [ 0 , 1 , '' , 'abc' , истина , ложь , {}];// Все следующие выражения эквивалентны.фильтр ( пример );фильтр ( например , не определено );фильтр ( например , iteratee ( undefined ));фильтр ( пример , личность );// [1, 'abc', истина, {}]
Переопределение _.iteratee
Пользователи могут переопределить _.iteratee для создания собственных сокращений. В следующем примере показано, как это можно использовать для реализации фильтрации регулярных выражений:
import { iteratee как originalIteratee , isRegExp , Mixin , фильтр ,} от «подчеркивания» ;функция iteratee ( значение , контекст ) { if ( isRegExp ( значение )) { вернуть строку => значение . тест ( строка ); } else { return originalIteratee ( значение , контекст ); }}миксин ({ итерация });filter ([ 'абсолютно' , 'потрясающе' , 'потрясающе' , 'брюки' ], / ab / );// ['абсолютно невероятно']
Смотрите также
- Лодаш
- Prototype.js
Рекомендации
- ^ Релиз 0.1.0 , jashkenas / подчеркивание, GitHub
- ^ "Underscore.js - ein kleines Framework mit Fokus" . entwickler.de (на немецком языке). 20 июня 2018 . Дата обращения 9 июля 2020 .
- ^ "JavaScript Meetup City" , открытый , The New York Times , 4 апреля 2012 г.
- ^ Ашкенас, Джереми. "Исходный код Underscore 0.4.0" . cdn.rawgit.com . Проверено 1 марта 2021 года .
- ^ «Lo-Dash v2.2.1» . lodash.com . Архивировано 6 ноября 2013 года . Проверено 1 марта 2021 года .CS1 maint: неподходящий URL ( ссылка )
- ^ «Журнал изменений Lodash - 1.0.0 RC1» . github.com . 4 декабря 2012 . Проверено 1 марта 2021 года .
- ^ «Журнал изменений Lodash - 3.0.0» . github.com . 26 января 2015 . Проверено 1 марта 2021 года .
- ^ Ашкенас, Джереми (21 мая 2015 г.). «Большой Кахуна: подчеркивание + нить слияния Lodash» . github.com . Проверено 1 марта 2021 года .
- ^ «Underscore: объединенные запросы на вытягивание с критическими изменениями в период с 21 мая по 1 октября 2015 года» . github.com . Проверено 1 марта 2021 года .
- ^ Далтон, Джон-Дэвид (8 июня 2015 г.). «комментарий к« Core API » » . github.com . Проверено 1 марта 2021 года .
- ^ «Журнал изменений Lodash 4.0.0» . github.com . 12 января 2016 . Проверено 1 марта 2021 года .
- ^ "@ sailshq / lodash" . npmjs.com . Проверено 1 марта 2021 года .
- ^ Далтон, Джон-Дэвид (13 февраля 2016 г.). "Слить обновление" . github.com . Проверено 1 марта 2021 года .
- ^ Кребс, Адам (17 февраля 2016 г.). "комментарий к" Обновление слияния. " " . github.com . Проверено 1 марта 2021 года .
- ^ а б "jashkenas / underscore Insights: авторы" . github.com . Проверено 1 марта 2021 года .
- ^ "lodash / lodash Insight: авторы" . github.com . Проверено 1 марта 2021 года .
- ^ «Array.prototype.map» . developer.mozilla.org . Проверено 1 марта 2021 года .
- ^ "Array.prototype.filter" . developer.mozilla.org . Проверено 1 марта 2021 года .
- ^ «Array.prototype.forEach» . developer.mozilla.org . Проверено 1 марта 2021 года .
- ^ "_.map" . underscorejs.org . Проверено 1 марта 2021 года .
- ^ "_.фильтр" . underscorejs.org . Проверено 1 марта 2021 года .
- ^ "_.each" . underscorejs.org . Проверено 1 марта 2021 года .
- ^ "Underscore.js" . underscorejs.org . Проверено 1 марта 2021 года .
- ^ «Справочник по JavaScript» . developer.mozilla.org . Проверено 1 марта 2021 года .
- ^ "подчеркивание" . npmjs.com . Проверено 1 марта 2021 года .
- ^ Gonggrijp, Джулиан. "модули / index.js" . underscorejs.org . Проверено 5 марта 2021 года .
- ^ Gonggrijp, Джулиан. «модули / index-default.js» . underscorejs.org . Проверено 4 марта 2021 года .
Внешние ссылки
- Официальный веб-сайт
- Функциональный Javascript Оливера Стила (интернет-архив; osteele.com сохраняет только снимок экрана )
- Микро-шаблоны JavaScript от Джона Ресига, оригинального источника вдохновения для_.template